]> granicus.if.org Git - vim/commitdiff
patch 8.2.0336: Vim9: insufficient test coverage for compiling v8.2.0336
authorBram Moolenaar <Bram@vim.org>
Sat, 29 Feb 2020 22:23:47 +0000 (23:23 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 29 Feb 2020 22:23:47 +0000 (23:23 +0100)
Problem:    Vim9: insufficient test coverage for compiling.
Solution:   Add more tests.

src/testdir/test_vim9_expr.vim
src/testdir/test_vim9_script.vim
src/version.c
src/vim9.h
src/vim9compile.c
src/vim9execute.c

index 5ece65274b8007a40b5a398ab31e082bf8718aae..1ec3c6f1b028482a6fbbcc2f7403fe1d0d125974 100644 (file)
@@ -9,6 +9,12 @@ func CheckDefFailure(line, error)
   call delete('Xdef')
 endfunc
 
+func CheckDefFailureMult(lines, error)
+  call writefile(['def! Func()'] + a:lines + ['enddef'], 'Xdef')
+  call assert_fails('so Xdef', a:error, join(a:lines, ' | '))
+  call delete('Xdef')
+endfunc
+
 " Check that "line" inside ":def" results in an "error" message when executed.
 func CheckDefExecFailure(line, error)
   call writefile(['def! Func()', a:line, 'enddef'], 'Xdef')
@@ -805,6 +811,8 @@ func Test_expr7_fails()
   call CheckDefExecFailure("let x = +g:ablob", 'E974:')
   call CheckDefExecFailure("let x = +g:alist", 'E745:')
   call CheckDefExecFailure("let x = +g:adict", 'E728:')
+
+  call CheckDefFailureMult(["let x = ''", "let y = x.memb"], 'E715:')
 endfunc
 
 let g:Funcrefs = [function('add')]
index f1b21d45e39d14441bd0f3478cb66af0fae3483d..ac8bd7512fe3c6c416d07bf6b478967ba1511b4b 100644 (file)
@@ -53,6 +53,10 @@ def Test_assignment()
   let dict4: dict<any> = #{one: 1, two: '2'}
   let dict5: dict<blob> = #{one: 0z01, tw: 0z02}
 
+  if has('channel')
+    let chan1: channel
+  endif
+
   g:newvar = 'new'
   assert_equal('new', g:newvar)
 
@@ -91,6 +95,21 @@ func Test_assignment_failure()
 
   call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
   call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
+
+  call CheckDefFailure(['let var: dict <number>'], 'E1007:')
+  call CheckDefFailure(['let var: dict<number'], 'E1009:')
+
+  call CheckDefFailure(['let var: ally'], 'E1010:')
+  call CheckDefFailure(['let var: bram'], 'E1010:')
+  call CheckDefFailure(['let var: cathy'], 'E1010:')
+  call CheckDefFailure(['let var: dom'], 'E1010:')
+  call CheckDefFailure(['let var: freddy'], 'E1010:')
+  call CheckDefFailure(['let var: john'], 'E1010:')
+  call CheckDefFailure(['let var: larry'], 'E1010:')
+  call CheckDefFailure(['let var: ned'], 'E1010:')
+  call CheckDefFailure(['let var: pam'], 'E1010:')
+  call CheckDefFailure(['let var: sam'], 'E1010:')
+  call CheckDefFailure(['let var: vim'], 'E1010:')
 endfunc
 
 func Test_const()
@@ -203,6 +222,12 @@ def Test_call_def_varargs()
   assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
 enddef
 
+def Test_using_var_as_arg()
+  call writefile(['def Func(x: number)',  'let x = 234', 'enddef'], 'Xdef')
+  call assert_fails('so Xdef', 'E1006:')
+  call delete('Xdef')
+enddef
+
 def Test_call_func_defined_later()
   call assert_equal('one', DefinedLater('one'))
   call assert_fails('call NotDefined("one")', 'E117:')
index 23c45082c7a49d250c0cea932aa159373e0435c5..06b95118161db4e1f3f9a72775538579789e46e5 100644 (file)
@@ -738,6 +738,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    336,
 /**/
     335,
 /**/
index 77bf626d6f583f1c158fa43731ca21ff2e7679d8..3a09c0fecb7d83f95be172b9dcd854fdf04cae6c 100644 (file)
@@ -39,14 +39,18 @@ typedef enum {
     ISN_STORENR,    // store number into local variable isn_arg.storenr.str_idx
 
     // constants
-    ISN_PUSHNR,            // push number isn_arg.number
-    ISN_PUSHBOOL,   // push bool value isn_arg.number
-    ISN_PUSHSPEC,   // push special value isn_arg.number
-    ISN_PUSHF,     // push float isn_arg.fnumber
-    ISN_PUSHS,     // push string isn_arg.string
-    ISN_PUSHBLOB,   // push blob isn_arg.blob
-    ISN_NEWLIST,    // push list from stack items, size is isn_arg.number
-    ISN_NEWDICT,    // push dict from stack items, size is isn_arg.number
+    ISN_PUSHNR,                // push number isn_arg.number
+    ISN_PUSHBOOL,      // push bool value isn_arg.number
+    ISN_PUSHSPEC,      // push special value isn_arg.number
+    ISN_PUSHF,         // push float isn_arg.fnumber
+    ISN_PUSHS,         // push string isn_arg.string
+    ISN_PUSHBLOB,      // push blob isn_arg.blob
+    ISN_PUSHFUNC,      // push func isn_arg.string
+    ISN_PUSHPARTIAL,   // push partial ?
+    ISN_PUSHCHANNEL,   // push channel isn_arg.channel
+    ISN_PUSHJOB,       // push channel isn_arg.job
+    ISN_NEWLIST,       // push list from stack items, size is isn_arg.number
+    ISN_NEWDICT,       // push dict from stack items, size is isn_arg.number
 
     // function call
     ISN_BCALL,     // call builtin function isn_arg.bfunc
@@ -209,6 +213,8 @@ typedef struct {
 #ifdef FEAT_FLOAT
        float_T             fnumber;
 #endif
+       channel_T           *channel;
+       job_T               *job;
        jump_T              jump;
        forloop_T           forloop;
        try_T               try;
index 35f20c4c76295056d7bbd68f69b31230dd9156b5..a4525ca0c167cb5187ba4c57422b49d4b8dfabf9 100644 (file)
@@ -641,6 +641,38 @@ generate_PUSHS(cctx_T *cctx, char_u *str)
     return OK;
 }
 
+/*
+ * Generate an ISN_PUSHCHANNEL instruction.
+ * Consumes "channel".
+ */
+    static int
+generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
+{
+    isn_T      *isn;
+
+    if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
+       return FAIL;
+    isn->isn_arg.channel = channel;
+
+    return OK;
+}
+
+/*
+ * Generate an ISN_PUSHJOB instruction.
+ * Consumes "job".
+ */
+    static int
+generate_PUSHJOB(cctx_T *cctx, job_T *job)
+{
+    isn_T      *isn;
+
+    if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
+       return FAIL;
+    isn->isn_arg.job = job;
+
+    return OK;
+}
+
 /*
  * Generate an ISN_PUSHBLOB instruction.
  * Consumes "blob".
@@ -657,6 +689,22 @@ generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
     return OK;
 }
 
+/*
+ * Generate an ISN_PUSHFUNC instruction with name "name".
+ * Consumes "name".
+ */
+    static int
+generate_PUSHFUNC(cctx_T *cctx, char_u *name)
+{
+    isn_T      *isn;
+
+    if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, &t_func_void)) == NULL)
+       return FAIL;
+    isn->isn_arg.string = name;
+
+    return OK;
+}
+
 /*
  * Generate an ISN_STORE instruction.
  */
@@ -3549,10 +3597,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
                generate_PUSHBLOB(cctx, NULL);
                break;
            case VAR_FUNC:
-               // generate_PUSHS(cctx, NULL); TODO
+               generate_PUSHFUNC(cctx, NULL);
                break;
            case VAR_PARTIAL:
-               // generate_PUSHS(cctx, NULL); TODO
+               // generate_PUSHPARTIAL(cctx, NULL);
+               emsg("Partial type not supported yet");
                break;
            case VAR_LIST:
                generate_NEWLIST(cctx, 0);
@@ -3561,10 +3610,10 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
                generate_NEWDICT(cctx, 0);
                break;
            case VAR_JOB:
-               // generate_PUSHS(cctx, NULL); TODO
+               generate_PUSHJOB(cctx, NULL);
                break;
            case VAR_CHANNEL:
-               // generate_PUSHS(cctx, NULL); TODO
+               generate_PUSHCHANNEL(cctx, NULL);
                break;
            case VAR_NUMBER:
            case VAR_UNKNOWN:
@@ -4748,6 +4797,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
     int                called_emsg_before = called_emsg;
     int                ret = FAIL;
     sctx_T     save_current_sctx = current_sctx;
+    int                emsg_before = called_emsg;
 
     if (ufunc->uf_dfunc_idx >= 0)
     {
@@ -4828,7 +4878,8 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
            ++line;
        else if (line != NULL && *line != NUL)
        {
-           semsg(_("E488: Trailing characters: %s"), line);
+           if (emsg_before == called_emsg)
+               semsg(_("E488: Trailing characters: %s"), line);
            goto erret;
        }
        else
@@ -4844,6 +4895,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
                break;
            SOURCING_LNUM = ufunc->uf_script_ctx.sc_lnum + cctx.ctx_lnum + 1;
        }
+       emsg_before = called_emsg;
 
        had_return = FALSE;
        vim_memset(&ea, 0, sizeof(ea));
@@ -5153,6 +5205,7 @@ delete_instr(isn_T *isn)
        case ISN_PUSHS:
        case ISN_STOREENV:
        case ISN_STOREG:
+       case ISN_PUSHFUNC:
            vim_free(isn->isn_arg.string);
            break;
 
@@ -5169,6 +5222,18 @@ delete_instr(isn_T *isn)
            blob_unref(isn->isn_arg.blob);
            break;
 
+       case ISN_PUSHPARTIAL:
+           // TODO
+           break;
+
+       case ISN_PUSHJOB:
+           job_unref(isn->isn_arg.job);
+           break;
+
+       case ISN_PUSHCHANNEL:
+           channel_unref(isn->isn_arg.channel);
+           break;
+
        case ISN_UCALL:
            vim_free(isn->isn_arg.ufunc.cuf_name);
            break;
index 5c5fcb1573330e195637f1f02d8a62200d24426f..9d187c4b44ec8f4ee71b665c35c1e2314c617597 100644 (file)
@@ -840,6 +840,10 @@ call_def_function(
            case ISN_PUSHF:
            case ISN_PUSHS:
            case ISN_PUSHBLOB:
+           case ISN_PUSHFUNC:
+           case ISN_PUSHPARTIAL:
+           case ISN_PUSHCHANNEL:
+           case ISN_PUSHJOB:
                if (ga_grow(&ectx.ec_stack, 1) == FAIL)
                    goto failed;
                tv = STACK_TV_BOT(0);
@@ -867,6 +871,29 @@ call_def_function(
                    case ISN_PUSHBLOB:
                        blob_copy(iptr->isn_arg.blob, tv);
                        break;
+                   case ISN_PUSHFUNC:
+                       tv->v_type = VAR_FUNC;
+                       tv->vval.v_string = vim_strsave(iptr->isn_arg.string);
+                       break;
+                   case ISN_PUSHPARTIAL:
+                       tv->v_type = VAR_UNKNOWN;
+                       break;
+                   case ISN_PUSHCHANNEL:
+#ifdef FEAT_JOB_CHANNEL
+                       tv->v_type = VAR_CHANNEL;
+                       tv->vval.v_channel = iptr->isn_arg.channel;
+                       if (tv->vval.v_channel != NULL)
+                           ++tv->vval.v_channel->ch_refcount;
+#endif
+                       break;
+                   case ISN_PUSHJOB:
+#ifdef FEAT_JOB_CHANNEL
+                       tv->v_type = VAR_JOB;
+                       tv->vval.v_job = iptr->isn_arg.job;
+                       if (tv->vval.v_job != NULL)
+                           ++tv->vval.v_job->jv_refcount;
+#endif
+                       break;
                    default:
                        tv->v_type = VAR_STRING;
                        tv->vval.v_string = vim_strsave(iptr->isn_arg.string);
@@ -1846,6 +1873,36 @@ ex_disassemble(exarg_T *eap)
                    vim_free(tofree);
                }
                break;
+           case ISN_PUSHFUNC:
+               smsg("%4d PUSHFUNC \"%s\"", current, iptr->isn_arg.string);
+               break;
+           case ISN_PUSHPARTIAL:
+               // TODO
+               smsg("%4d PUSHPARTIAL", current);
+               break;
+           case ISN_PUSHCHANNEL:
+#ifdef FEAT_JOB_CHANNEL
+               {
+                   channel_T *channel = iptr->isn_arg.channel;
+
+                   smsg("%4d PUSHCHANNEL %d", current,
+                                        channel == NULL ? 0 : channel->ch_id);
+               }
+#endif
+               break;
+           case ISN_PUSHJOB:
+#ifdef FEAT_JOB_CHANNEL
+               {
+                   typval_T    tv;
+                   char_u      *name;
+
+                   tv.v_type = VAR_JOB;
+                   tv.vval.v_job = iptr->isn_arg.job;
+                   name = tv_get_string(&tv);
+                   smsg("%4d PUSHJOB %s", current, name);
+               }
+#endif
+               break;
            case ISN_PUSHEXC:
                smsg("%4d PUSH v:exception", current);
                break;