summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-04-10 13:33:48 +0200
committerBram Moolenaar <Bram@vim.org>2021-04-10 13:33:48 +0200
commit701cc6ca9e940665a9424541f989bb38c853a498 (patch)
treefc921ae870560511c19e0caa9025fcbc568143de
parent1088b69451c739c698cf4c2003c2b994458ad18b (diff)
patch 8.2.2742: Vim9: when compiling a function fails it is clearedv8.2.2742
Problem: Vim9: when compiling a function fails it is cleared. Solution: Keep the function lines, prevent execution with a different status. (closes #8093)
-rw-r--r--src/structs.h9
-rw-r--r--src/testdir/test_vim9_func.vim16
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c19
-rw-r--r--src/vim9execute.c1
5 files changed, 34 insertions, 13 deletions
diff --git a/src/structs.h b/src/structs.h
index dd802152c2..b4bafa5a98 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1583,10 +1583,11 @@ typedef struct funccall_S funccall_T;
// values used for "uf_def_status"
typedef enum {
- UF_NOT_COMPILED,
- UF_TO_BE_COMPILED,
- UF_COMPILING,
- UF_COMPILED
+ UF_NOT_COMPILED, // executed with interpreter
+ UF_TO_BE_COMPILED, // to be compiled before execution
+ UF_COMPILING, // in compile_def_function()
+ UF_COMPILED, // successfully compiled
+ UF_COMPILE_ERROR // compilation error, cannot execute
} def_status_T;
/*
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index 85830a36ce..6a3dfbbe6d 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -1498,7 +1498,7 @@ def Test_redef_failure()
so Xdef
delete('Xdef')
- g:Func0()->assert_equal(0)
+ assert_fails('g:Func0()', 'E1091:')
g:Func1()->assert_equal('Func1')
g:Func2()->assert_equal('Func2')
@@ -2591,6 +2591,20 @@ def Test_check_func_arg_types()
CheckScriptFailure(lines + ['echo H(G(F2))'], 'E1013:')
enddef
+def Test_compile_error()
+ var lines =<< trim END
+ def g:Broken()
+ echo 'a' + {}
+ enddef
+ call g:Broken()
+ END
+ # First call: compilation error
+ CheckScriptFailure(lines, 'E1051: Wrong argument type for +')
+
+ # Second call won't try compiling again
+ assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken')
+enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/version.c b/src/version.c
index 64c5af40b2..5cf56feadc 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2742,
+/**/
2741,
/**/
2740,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index c2735dcbd4..aa5894a355 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1791,8 +1791,9 @@ func_needs_compiling(ufunc_T *ufunc, int profile UNUSED)
{
switch (ufunc->uf_def_status)
{
- case UF_NOT_COMPILED: break;
- case UF_TO_BE_COMPILED: return TRUE;
+ case UF_TO_BE_COMPILED:
+ return TRUE;
+
case UF_COMPILED:
{
#ifdef FEAT_PROFILE
@@ -1805,7 +1806,11 @@ func_needs_compiling(ufunc_T *ufunc, int profile UNUSED)
break;
#endif
}
- case UF_COMPILING: break;
+
+ case UF_NOT_COMPILED:
+ case UF_COMPILE_ERROR:
+ case UF_COMPILING:
+ break;
}
return FALSE;
}
@@ -1834,7 +1839,8 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
return FAIL;
}
- if (ufunc->uf_def_status != UF_NOT_COMPILED)
+ if (ufunc->uf_def_status != UF_NOT_COMPILED
+ && ufunc->uf_def_status != UF_COMPILE_ERROR)
{
int i;
@@ -9007,14 +9013,11 @@ erret:
--def_functions.ga_len;
ufunc->uf_dfunc_idx = 0;
}
- ufunc->uf_def_status = UF_NOT_COMPILED;
+ ufunc->uf_def_status = UF_COMPILE_ERROR;
while (cctx.ctx_scope != NULL)
drop_scope(&cctx);
- // Don't execute this function body.
- ga_clear_strings(&ufunc->uf_lines);
-
if (errormsg != NULL)
emsg(errormsg);
else if (did_emsg == did_emsg_before)
diff --git a/src/vim9execute.c b/src/vim9execute.c
index eddb90f9ff..a49d305532 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1297,6 +1297,7 @@ call_def_function(
#define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx)
if (ufunc->uf_def_status == UF_NOT_COMPILED
+ || ufunc->uf_def_status == UF_COMPILE_ERROR
|| (func_needs_compiling(ufunc, PROFILING(ufunc))
&& compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL)
== FAIL))