summaryrefslogtreecommitdiff
path: root/src/vim9compile.c
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2022-04-21 23:30:15 +0100
committerBram Moolenaar <Bram@vim.org>2022-04-21 23:30:15 +0100
commit1fc6ea9bf3548b578676331f5eac1f7e0611c268 (patch)
treecbbabd2cece75b8657356b2b1716372daeee94ce /src/vim9compile.c
parent66e13aedc7986c83644d537a8fdd3cb006507678 (diff)
downloadvim-git-1fc6ea9bf3548b578676331f5eac1f7e0611c268.tar.gz
patch 8.2.4804: expression in heredoc doesn't work for compiled functionv8.2.4804
Problem: Expression in heredoc doesn't work for compiled function. Solution: Implement compiling the heredoc expressions. (Yegappan Lakshmanan, closes #10232)
Diffstat (limited to 'src/vim9compile.c')
-rw-r--r--src/vim9compile.c91
1 files changed, 79 insertions, 12 deletions
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 205d9a9a6..88a4d57d7 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -595,6 +595,7 @@ find_imported_in_script(char_u *name, size_t len, int sid)
/*
* Find "name" in imported items of the current script.
+ * If "len" is 0 use any length that works.
* If "load" is TRUE and the script was not loaded yet, load it now.
*/
imported_T *
@@ -968,6 +969,83 @@ theend:
}
/*
+ * Compile a heredoc string "str" (either containing a literal string or a mix
+ * of literal strings and Vim expressions of the form `=<expr>`). This is used
+ * when compiling a heredoc assignment to a variable in a Vim9 def function.
+ * Vim9 instructions are generated to push strings, evaluate expressions,
+ * concatenate them and create a list of lines. When "evalstr" is TRUE, Vim
+ * expressions in "str" are evaluated.
+ */
+ int
+compile_heredoc_string(char_u *str, int evalstr, cctx_T *cctx)
+{
+ char_u *p;
+ char_u *val;
+
+ if (cctx->ctx_skip == SKIP_YES)
+ return OK;
+
+ if (evalstr && (p = (char_u *)strstr((char *)str, "`=")) != NULL)
+ {
+ char_u *start = str;
+
+ // Need to evaluate expressions of the form `=<expr>` in the string.
+ // Split the string into literal strings and Vim expressions and
+ // generate instructions to concatenate the literal strings and the
+ // result of evaluating the Vim expressions.
+ val = vim_strsave((char_u *)"");
+ generate_PUSHS(cctx, &val);
+
+ for (;;)
+ {
+ if (p > start)
+ {
+ // literal string before the expression
+ val = vim_strnsave(start, p - start);
+ generate_PUSHS(cctx, &val);
+ generate_instr_drop(cctx, ISN_CONCAT, 1);
+ }
+ p += 2;
+
+ // evaluate the Vim expression and convert the result to string.
+ if (compile_expr0(&p, cctx) == FAIL)
+ return FAIL;
+ may_generate_2STRING(-1, TRUE, cctx);
+ generate_instr_drop(cctx, ISN_CONCAT, 1);
+
+ p = skipwhite(p);
+ if (*p != '`')
+ {
+ emsg(_(e_missing_backtick));
+ return FAIL;
+ }
+ start = p + 1;
+
+ p = (char_u *)strstr((char *)start, "`=");
+ if (p == NULL)
+ {
+ // no more Vim expressions left to process
+ if (*skipwhite(start) != NUL)
+ {
+ val = vim_strsave(start);
+ generate_PUSHS(cctx, &val);
+ generate_instr_drop(cctx, ISN_CONCAT, 1);
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ // literal string
+ val = vim_strsave(str);
+ generate_PUSHS(cctx, &val);
+ }
+
+ return OK;
+}
+
+/*
* Return the length of an assignment operator, or zero if there isn't one.
*/
int
@@ -1946,25 +2024,14 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
if (heredoc)
{
list_T *l;
- listitem_T *li;
// [let] varname =<< [trim] {end}
eap->getline = exarg_getline;
eap->cookie = cctx;
- l = heredoc_get(eap, op + 3, FALSE);
+ l = heredoc_get(eap, op + 3, FALSE, TRUE);
if (l == NULL)
return NULL;
- if (cctx->ctx_skip != SKIP_YES)
- {
- // Push each line and the create the list.
- FOR_ALL_LIST_ITEMS(l, li)
- {
- generate_PUSHS(cctx, &li->li_tv.vval.v_string);
- li->li_tv.vval.v_string = NULL;
- }
- generate_NEWLIST(cctx, l->lv_len, FALSE);
- }
list_free(l);
p += STRLEN(p);
end = p;