comparison 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
comparison
equal deleted inserted replaced
28691:ca54846af861 28692:bfd8e25fa207
565 return res; 565 return res;
566 } 566 }
567 567
568 /* 568 /*
569 * Compile a string in a ISN_PUSHS instruction into an ISN_INSTR. 569 * Compile a string in a ISN_PUSHS instruction into an ISN_INSTR.
570 * "str_offset" is the number of leading bytes to skip from the string.
570 * Returns FAIL if compilation fails. 571 * Returns FAIL if compilation fails.
571 */ 572 */
572 static int 573 static int
573 compile_string(isn_T *isn, cctx_T *cctx) 574 compile_string(isn_T *isn, cctx_T *cctx, int str_offset)
574 { 575 {
575 char_u *s = isn->isn_arg.string; 576 char_u *s = isn->isn_arg.string + str_offset;
576 garray_T save_ga = cctx->ctx_instr; 577 garray_T save_ga = cctx->ctx_instr;
577 int expr_res; 578 int expr_res;
578 int trailing_error; 579 int trailing_error;
579 int instr_count; 580 int instr_count;
580 isn_T *instr = NULL; 581 isn_T *instr = NULL;
614 isn->isn_arg.instr = instr; 615 isn->isn_arg.instr = instr;
615 return OK; 616 return OK;
616 } 617 }
617 618
618 /* 619 /*
620 * List of special functions for "compile_arguments".
621 */
622 typedef enum {
623 CA_NOT_SPECIAL,
624 CA_SEARCHPAIR, // {skip} in searchpair() and searchpairpos()
625 CA_SUBSTITUTE, // {sub} in substitute(), when prefixed with \=
626 } ca_special_T;
627
628 /*
619 * Compile the argument expressions. 629 * Compile the argument expressions.
620 * "arg" points to just after the "(" and is advanced to after the ")" 630 * "arg" points to just after the "(" and is advanced to after the ")"
621 */ 631 */
622 static int 632 static int
623 compile_arguments(char_u **arg, cctx_T *cctx, int *argcount, int is_searchpair) 633 compile_arguments(
634 char_u **arg,
635 cctx_T *cctx,
636 int *argcount,
637 ca_special_T special_fn)
624 { 638 {
625 char_u *p = *arg; 639 char_u *p = *arg;
626 char_u *whitep = *arg; 640 char_u *whitep = *arg;
627 int must_end = FALSE; 641 int must_end = FALSE;
628 int instr_count; 642 int instr_count;
645 instr_count = cctx->ctx_instr.ga_len; 659 instr_count = cctx->ctx_instr.ga_len;
646 if (compile_expr0(&p, cctx) == FAIL) 660 if (compile_expr0(&p, cctx) == FAIL)
647 return FAIL; 661 return FAIL;
648 ++*argcount; 662 ++*argcount;
649 663
650 if (is_searchpair && *argcount == 5 664 if (special_fn == CA_SEARCHPAIR && *argcount == 5
651 && cctx->ctx_instr.ga_len == instr_count + 1) 665 && cctx->ctx_instr.ga_len == instr_count + 1)
652 { 666 {
653 isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count; 667 isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count;
654 668
655 // {skip} argument of searchpair() can be compiled if not empty 669 // {skip} argument of searchpair() can be compiled if not empty
656 if (isn->isn_type == ISN_PUSHS && *isn->isn_arg.string != NUL) 670 if (isn->isn_type == ISN_PUSHS && *isn->isn_arg.string != NUL)
657 compile_string(isn, cctx); 671 compile_string(isn, cctx, 0);
672 }
673 else if (special_fn == CA_SUBSTITUTE && *argcount == 3
674 && cctx->ctx_instr.ga_len == instr_count + 1)
675 {
676 isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count;
677
678 // {sub} argument of substitute() can be compiled if it starts
679 // with \=
680 if (isn->isn_type == ISN_PUSHS && isn->isn_arg.string[0] == '\\'
681 && isn->isn_arg.string[1] == '=')
682 compile_string(isn, cctx, 2);
658 } 683 }
659 684
660 if (*p != ',' && *skipwhite(p) == ',') 685 if (*p != ',' && *skipwhite(p) == ',')
661 { 686 {
662 semsg(_(e_no_white_space_allowed_before_str_str), ",", p); 687 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
704 int error = FCERR_NONE; 729 int error = FCERR_NONE;
705 ufunc_T *ufunc = NULL; 730 ufunc_T *ufunc = NULL;
706 int res = FAIL; 731 int res = FAIL;
707 int is_autoload; 732 int is_autoload;
708 int has_g_namespace; 733 int has_g_namespace;
709 int is_searchpair; 734 ca_special_T special_fn;
710 imported_T *import; 735 imported_T *import;
711 736
712 if (varlen >= sizeof(namebuf)) 737 if (varlen >= sizeof(namebuf))
713 { 738 {
714 semsg(_(e_name_too_long_str), name); 739 semsg(_(e_name_too_long_str), name);
774 799
775 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error); 800 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
776 801
777 // We handle the "skip" argument of searchpair() and searchpairpos() 802 // We handle the "skip" argument of searchpair() and searchpairpos()
778 // differently. 803 // differently.
779 is_searchpair = (varlen == 6 && STRNCMP(*arg, "search", 6) == 0) 804 if ((varlen == 6 && STRNCMP(*arg, "search", 6) == 0)
780 || (varlen == 9 && STRNCMP(*arg, "searchpos", 9) == 0) 805 || (varlen == 9 && STRNCMP(*arg, "searchpos", 9) == 0)
781 || (varlen == 10 && STRNCMP(*arg, "searchpair", 10) == 0) 806 || (varlen == 10 && STRNCMP(*arg, "searchpair", 10) == 0)
782 || (varlen == 13 && STRNCMP(*arg, "searchpairpos", 13) == 0); 807 || (varlen == 13 && STRNCMP(*arg, "searchpairpos", 13) == 0))
808 special_fn = CA_SEARCHPAIR;
809 else if (varlen == 10 && STRNCMP(*arg, "substitute", 10) == 0)
810 special_fn = CA_SUBSTITUTE;
811 else
812 special_fn = CA_NOT_SPECIAL;
783 813
784 *arg = skipwhite(*arg + varlen + 1); 814 *arg = skipwhite(*arg + varlen + 1);
785 if (compile_arguments(arg, cctx, &argcount, is_searchpair) == FAIL) 815 if (compile_arguments(arg, cctx, &argcount, special_fn) == FAIL)
786 goto theend; 816 goto theend;
787 817
788 is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL; 818 is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
789 if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload) 819 if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
790 { 820 {
1715 1745
1716 // funcref(arg) 1746 // funcref(arg)
1717 type = get_type_on_stack(cctx, 0); 1747 type = get_type_on_stack(cctx, 0);
1718 1748
1719 *arg = skipwhite(p + 1); 1749 *arg = skipwhite(p + 1);
1720 if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL) 1750 if (compile_arguments(arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
1721 return FAIL; 1751 return FAIL;
1722 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL) 1752 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
1723 return FAIL; 1753 return FAIL;
1724 if (keeping_dict) 1754 if (keeping_dict)
1725 { 1755 {
1846 // Remember the next instruction index, where the instructions 1876 // Remember the next instruction index, where the instructions
1847 // for arguments are being written. 1877 // for arguments are being written.
1848 expr_isn_end = cctx->ctx_instr.ga_len; 1878 expr_isn_end = cctx->ctx_instr.ga_len;
1849 1879
1850 *arg = skipwhite(*arg + 1); 1880 *arg = skipwhite(*arg + 1);
1851 if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL) 1881 if (compile_arguments(arg, cctx, &argcount, CA_NOT_SPECIAL)
1882 == FAIL)
1852 return FAIL; 1883 return FAIL;
1853 1884
1854 // Move the instructions for the arguments to before the 1885 // Move the instructions for the arguments to before the
1855 // instructions of the expression and move the type of the 1886 // instructions of the expression and move the type of the
1856 // expression after the argument types. This is what ISN_PCALL 1887 // expression after the argument types. This is what ISN_PCALL