Mercurial > vim
comparison src/vim9compile.c @ 24512:53871095bb65 v8.2.2796
patch 8.2.2796: Vim9: redir to variable does not accept an index
Commit: https://github.com/vim/vim/commit/753bcf8c7d7cf7b9e1572a80cc513a67020814ac
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Apr 21 14:24:24 2021 +0200
patch 8.2.2796: Vim9: redir to variable does not accept an index
Problem: Vim9: redir to variable does not accept an index.
Solution: Make the index work.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 21 Apr 2021 14:30:04 +0200 |
parents | b5786b4de9d1 |
children | 056f954c6fd2 |
comparison
equal
deleted
inserted
replaced
24511:2aaa71ea39fb | 24512:53871095bb65 |
---|---|
132 // Used by compile_lhs() to store information about the LHS of an assignment | 132 // Used by compile_lhs() to store information about the LHS of an assignment |
133 // and one argument of ":unlet" with an index. | 133 // and one argument of ":unlet" with an index. |
134 typedef struct { | 134 typedef struct { |
135 assign_dest_T lhs_dest; // type of destination | 135 assign_dest_T lhs_dest; // type of destination |
136 | 136 |
137 char_u *lhs_name; // allocated name including | 137 char_u *lhs_name; // allocated name excluding the last |
138 // "[expr]" or ".name". | 138 // "[expr]" or ".name". |
139 size_t lhs_varlen; // length of the variable without | 139 size_t lhs_varlen; // length of the variable without |
140 // "[expr]" or ".name" | 140 // "[expr]" or ".name" |
141 char_u *lhs_whole; // allocated name including the last | |
142 // "[expr]" or ".name" for :redir | |
143 size_t lhs_varlen_total; // length of the variable including | |
144 // any "[expr]" or ".name" | |
141 char_u *lhs_dest_end; // end of the destination, including | 145 char_u *lhs_dest_end; // end of the destination, including |
142 // "[expr]" or ".name". | 146 // "[expr]" or ".name". |
143 | 147 |
144 int lhs_has_index; // has "[expr]" or ".name" | 148 int lhs_has_index; // has "[expr]" or ".name" |
145 | 149 |
5843 if (is_decl && var_end == var_start + 2 && var_end[-1] == ':') | 5847 if (is_decl && var_end == var_start + 2 && var_end[-1] == ':') |
5844 --var_end; | 5848 --var_end; |
5845 | 5849 |
5846 // compute the length of the destination without "[expr]" or ".name" | 5850 // compute the length of the destination without "[expr]" or ".name" |
5847 lhs->lhs_varlen = var_end - var_start; | 5851 lhs->lhs_varlen = var_end - var_start; |
5852 lhs->lhs_varlen_total = lhs->lhs_varlen; | |
5848 lhs->lhs_name = vim_strnsave(var_start, lhs->lhs_varlen); | 5853 lhs->lhs_name = vim_strnsave(var_start, lhs->lhs_varlen); |
5849 if (lhs->lhs_name == NULL) | 5854 if (lhs->lhs_name == NULL) |
5850 return FAIL; | 5855 return FAIL; |
5851 | 5856 |
5852 if (lhs->lhs_dest_end > var_start + lhs->lhs_varlen) | 5857 if (lhs->lhs_dest_end > var_start + lhs->lhs_varlen) |
6071 // "ll[1][2]" the expression is "ll[1]" and "[2]" is the index. | 6076 // "ll[1][2]" the expression is "ll[1]" and "[2]" is the index. |
6072 for (;;) | 6077 for (;;) |
6073 { | 6078 { |
6074 p = skip_index(after); | 6079 p = skip_index(after); |
6075 if (*p != '[' && *p != '.') | 6080 if (*p != '[' && *p != '.') |
6081 { | |
6082 lhs->lhs_varlen_total = p - var_start; | |
6076 break; | 6083 break; |
6084 } | |
6077 after = p; | 6085 after = p; |
6078 } | 6086 } |
6079 if (after > var_start + lhs->lhs_varlen) | 6087 if (after > var_start + lhs->lhs_varlen) |
6080 { | 6088 { |
6081 lhs->lhs_varlen = after - var_start; | 6089 lhs->lhs_varlen = after - var_start; |
8590 | 8598 |
8591 static char_u * | 8599 static char_u * |
8592 compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx) | 8600 compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx) |
8593 { | 8601 { |
8594 char_u *arg = eap->arg; | 8602 char_u *arg = eap->arg; |
8595 | 8603 lhs_T *lhs = &cctx->ctx_redir_lhs; |
8596 if (cctx->ctx_redir_lhs.lhs_name != NULL) | 8604 |
8605 if (lhs->lhs_name != NULL) | |
8597 { | 8606 { |
8598 if (STRNCMP(arg, "END", 3) == 0) | 8607 if (STRNCMP(arg, "END", 3) == 0) |
8599 { | 8608 { |
8600 if (cctx->ctx_redir_lhs.lhs_append) | 8609 if (lhs->lhs_append) |
8601 { | 8610 { |
8602 if (compile_load_lhs(&cctx->ctx_redir_lhs, | 8611 if (compile_load_lhs(lhs, lhs->lhs_name, NULL, cctx) == FAIL) |
8603 cctx->ctx_redir_lhs.lhs_name, NULL, cctx) == FAIL) | |
8604 return NULL; | 8612 return NULL; |
8605 if (cctx->ctx_redir_lhs.lhs_has_index) | 8613 if (lhs->lhs_has_index) |
8606 emsg("redir with index not implemented yet"); | 8614 emsg("redir with index not implemented yet"); |
8607 } | 8615 } |
8608 | 8616 |
8609 // Gets the redirected text and put it on the stack, then store it | 8617 // Gets the redirected text and put it on the stack, then store it |
8610 // in the variable. | 8618 // in the variable. |
8611 generate_instr_type(cctx, ISN_REDIREND, &t_string); | 8619 generate_instr_type(cctx, ISN_REDIREND, &t_string); |
8612 | 8620 |
8613 if (cctx->ctx_redir_lhs.lhs_append) | 8621 if (lhs->lhs_append) |
8614 generate_instr_drop(cctx, ISN_CONCAT, 1); | 8622 generate_instr_drop(cctx, ISN_CONCAT, 1); |
8615 | 8623 |
8616 if (generate_store_lhs(cctx, &cctx->ctx_redir_lhs, -1) == FAIL) | 8624 if (lhs->lhs_has_index) |
8625 { | |
8626 // Use the info in "lhs" to store the value at the index in the | |
8627 // list or dict. | |
8628 if (compile_assign_unlet(lhs->lhs_whole, lhs, TRUE, | |
8629 &t_string, cctx) == FAIL) | |
8630 return NULL; | |
8631 } | |
8632 else if (generate_store_lhs(cctx, lhs, -1) == FAIL) | |
8617 return NULL; | 8633 return NULL; |
8618 | 8634 |
8619 VIM_CLEAR(cctx->ctx_redir_lhs.lhs_name); | 8635 VIM_CLEAR(lhs->lhs_name); |
8636 VIM_CLEAR(lhs->lhs_whole); | |
8620 return arg + 3; | 8637 return arg + 3; |
8621 } | 8638 } |
8622 emsg(_(e_cannot_nest_redir)); | 8639 emsg(_(e_cannot_nest_redir)); |
8623 return NULL; | 8640 return NULL; |
8624 } | 8641 } |
8625 | 8642 |
8626 if (arg[0] == '=' && arg[1] == '>') | 8643 if (arg[0] == '=' && arg[1] == '>') |
8627 { | 8644 { |
8628 int append = FALSE; | 8645 int append = FALSE; |
8629 | 8646 |
8630 // redirect to a variable is compiled | 8647 // redirect to a variable is compiled |
8631 arg += 2; | 8648 arg += 2; |
8632 if (*arg == '>') | 8649 if (*arg == '>') |
8633 { | 8650 { |
8634 ++arg; | 8651 ++arg; |
8635 append = TRUE; | 8652 append = TRUE; |
8636 } | 8653 } |
8637 arg = skipwhite(arg); | 8654 arg = skipwhite(arg); |
8638 | 8655 |
8639 if (compile_assign_lhs(arg, &cctx->ctx_redir_lhs, CMD_redir, | 8656 if (compile_assign_lhs(arg, lhs, CMD_redir, |
8640 FALSE, FALSE, 1, cctx) == FAIL) | 8657 FALSE, FALSE, 1, cctx) == FAIL) |
8641 return NULL; | 8658 return NULL; |
8642 generate_instr(cctx, ISN_REDIRSTART); | 8659 generate_instr(cctx, ISN_REDIRSTART); |
8643 cctx->ctx_redir_lhs.lhs_append = append; | 8660 lhs->lhs_append = append; |
8644 | 8661 if (lhs->lhs_has_index) |
8645 return arg + cctx->ctx_redir_lhs.lhs_varlen; | 8662 { |
8663 lhs->lhs_whole = vim_strnsave(arg, lhs->lhs_varlen_total); | |
8664 if (lhs->lhs_whole == NULL) | |
8665 return NULL; | |
8666 } | |
8667 | |
8668 return arg + lhs->lhs_varlen_total; | |
8646 } | 8669 } |
8647 | 8670 |
8648 // other redirects are handled like at script level | 8671 // other redirects are handled like at script level |
8649 return compile_exec(line, eap, cctx); | 8672 return compile_exec(line, eap, cctx); |
8650 } | 8673 } |
9333 { | 9356 { |
9334 emsg(_(e_missing_redir_end)); | 9357 emsg(_(e_missing_redir_end)); |
9335 ret = FAIL; | 9358 ret = FAIL; |
9336 } | 9359 } |
9337 vim_free(cctx.ctx_redir_lhs.lhs_name); | 9360 vim_free(cctx.ctx_redir_lhs.lhs_name); |
9361 vim_free(cctx.ctx_redir_lhs.lhs_whole); | |
9338 } | 9362 } |
9339 | 9363 |
9340 current_sctx = save_current_sctx; | 9364 current_sctx = save_current_sctx; |
9341 estack_compiling = save_estack_compiling; | 9365 estack_compiling = save_estack_compiling; |
9342 if (do_estack_push) | 9366 if (do_estack_push) |