Mercurial > vim
diff src/vim9expr.c @ 28692:bfd8e25fa207 v8.2.4870
patch 8.2.4870: Vim9: expression in :substitute is not compiled
Commit: https://github.com/vim/vim/commit/f3b4895f2727e3849ca10030b251cccd9d1383f3
Author: LemonBoy <thatlemon@gmail.com>
Date: Thu May 5 13:53:03 2022 +0100
patch 8.2.4870: Vim9: expression in :substitute is not compiled
Problem: Vim9: expression in :substitute is not compiled.
Solution: Use an INSTR instruction if possible. (closes https://github.com/vim/vim/issues/10334)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Thu, 05 May 2022 15:00:04 +0200 |
parents | d550054e1328 |
children | 723c7d940cba |
line wrap: on
line diff
--- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -567,12 +567,13 @@ theend: /* * Compile a string in a ISN_PUSHS instruction into an ISN_INSTR. + * "str_offset" is the number of leading bytes to skip from the string. * Returns FAIL if compilation fails. */ static int -compile_string(isn_T *isn, cctx_T *cctx) +compile_string(isn_T *isn, cctx_T *cctx, int str_offset) { - char_u *s = isn->isn_arg.string; + char_u *s = isn->isn_arg.string + str_offset; garray_T save_ga = cctx->ctx_instr; int expr_res; int trailing_error; @@ -616,11 +617,24 @@ compile_string(isn_T *isn, cctx_T *cctx) } /* + * List of special functions for "compile_arguments". + */ +typedef enum { + CA_NOT_SPECIAL, + CA_SEARCHPAIR, // {skip} in searchpair() and searchpairpos() + CA_SUBSTITUTE, // {sub} in substitute(), when prefixed with \= +} ca_special_T; + +/* * Compile the argument expressions. * "arg" points to just after the "(" and is advanced to after the ")" */ static int -compile_arguments(char_u **arg, cctx_T *cctx, int *argcount, int is_searchpair) +compile_arguments( + char_u **arg, + cctx_T *cctx, + int *argcount, + ca_special_T special_fn) { char_u *p = *arg; char_u *whitep = *arg; @@ -647,14 +661,25 @@ compile_arguments(char_u **arg, cctx_T * return FAIL; ++*argcount; - if (is_searchpair && *argcount == 5 + if (special_fn == CA_SEARCHPAIR && *argcount == 5 && cctx->ctx_instr.ga_len == instr_count + 1) { isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count; // {skip} argument of searchpair() can be compiled if not empty if (isn->isn_type == ISN_PUSHS && *isn->isn_arg.string != NUL) - compile_string(isn, cctx); + compile_string(isn, cctx, 0); + } + else if (special_fn == CA_SUBSTITUTE && *argcount == 3 + && cctx->ctx_instr.ga_len == instr_count + 1) + { + isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count; + + // {sub} argument of substitute() can be compiled if it starts + // with \= + if (isn->isn_type == ISN_PUSHS && isn->isn_arg.string[0] == '\\' + && isn->isn_arg.string[1] == '=') + compile_string(isn, cctx, 2); } if (*p != ',' && *skipwhite(p) == ',') @@ -706,7 +731,7 @@ compile_call( int res = FAIL; int is_autoload; int has_g_namespace; - int is_searchpair; + ca_special_T special_fn; imported_T *import; if (varlen >= sizeof(namebuf)) @@ -776,13 +801,18 @@ compile_call( // We handle the "skip" argument of searchpair() and searchpairpos() // differently. - is_searchpair = (varlen == 6 && STRNCMP(*arg, "search", 6) == 0) - || (varlen == 9 && STRNCMP(*arg, "searchpos", 9) == 0) - || (varlen == 10 && STRNCMP(*arg, "searchpair", 10) == 0) - || (varlen == 13 && STRNCMP(*arg, "searchpairpos", 13) == 0); + if ((varlen == 6 && STRNCMP(*arg, "search", 6) == 0) + || (varlen == 9 && STRNCMP(*arg, "searchpos", 9) == 0) + || (varlen == 10 && STRNCMP(*arg, "searchpair", 10) == 0) + || (varlen == 13 && STRNCMP(*arg, "searchpairpos", 13) == 0)) + special_fn = CA_SEARCHPAIR; + else if (varlen == 10 && STRNCMP(*arg, "substitute", 10) == 0) + special_fn = CA_SUBSTITUTE; + else + special_fn = CA_NOT_SPECIAL; *arg = skipwhite(*arg + varlen + 1); - if (compile_arguments(arg, cctx, &argcount, is_searchpair) == FAIL) + if (compile_arguments(arg, cctx, &argcount, special_fn) == FAIL) goto theend; is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL; @@ -1717,7 +1747,7 @@ compile_subscript( type = get_type_on_stack(cctx, 0); *arg = skipwhite(p + 1); - if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL) + if (compile_arguments(arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL) return FAIL; if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL) return FAIL; @@ -1848,7 +1878,8 @@ compile_subscript( expr_isn_end = cctx->ctx_instr.ga_len; *arg = skipwhite(*arg + 1); - if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL) + if (compile_arguments(arg, cctx, &argcount, CA_NOT_SPECIAL) + == FAIL) return FAIL; // Move the instructions for the arguments to before the