Mirror of the Vim source from https://github.com/vim/vim
Revisão | 846fbbacce3a4535b95d9557bcc580be12f327fa (tree) |
---|---|
Hora | 2020-04-01 06:15:04 |
Autor | Bram Moolenaar <Bram@vim....> |
Commiter | Bram Moolenaar |
patch 8.2.0487: Vim9: compiling not sufficiently tested
Commit: https://github.com/vim/vim/commit/bd5da371aafe5a2207065643502f4d1ff6b286c7
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Mar 31 23:13:10 2020 +0200
@@ -224,6 +224,31 @@ | ||
224 | 224 | enddef |
225 | 225 | |
226 | 226 | |
227 | +def EchoArg(arg: string): string | |
228 | + return arg | |
229 | +enddef | |
230 | +def RefThis(): func | |
231 | + return function('EchoArg') | |
232 | +enddef | |
233 | +def s:ScriptPCall() | |
234 | + RefThis()("text") | |
235 | +enddef | |
236 | + | |
237 | +def Test_disassemble_pcall() | |
238 | + let res = execute('disass s:ScriptPCall') | |
239 | + assert_match('<SNR>\d\+_ScriptPCall.*' | |
240 | + \ .. 'RefThis()("text").*' | |
241 | + \ .. '\d DCALL RefThis(argc 0).*' | |
242 | + \ .. '\d PUSHS "text".*' | |
243 | + \ .. '\d PCALL top (argc 1).*' | |
244 | + \ .. '\d PCALL end.*' | |
245 | + \ .. '\d DROP.*' | |
246 | + \ .. '\d PUSHNR 0.*' | |
247 | + \ .. '\d RETURN.*' | |
248 | + \, res) | |
249 | +enddef | |
250 | + | |
251 | + | |
227 | 252 | def FuncWithForwardCall(): string |
228 | 253 | return DefinedLater("yes") |
229 | 254 | enddef |
@@ -260,9 +260,10 @@ | ||
260 | 260 | echo a:arg |
261 | 261 | endfunc |
262 | 262 | |
263 | -def Test_call_wrong_arg_count() | |
263 | +def Test_call_wrong_args() | |
264 | 264 | call CheckDefFailure(['TakesOneArg()'], 'E119:') |
265 | 265 | call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:') |
266 | + call CheckDefFailure(['bufnr(xxx)'], 'E1001:') | |
266 | 267 | enddef |
267 | 268 | |
268 | 269 | " Default arg and varargs |
@@ -1029,6 +1030,14 @@ | ||
1029 | 1030 | assert_equal('1_3_', result) |
1030 | 1031 | enddef |
1031 | 1032 | |
1033 | +def Test_for_loop_fails() | |
1034 | + call CheckDefFailure(['for # in range(5)'], 'E690:') | |
1035 | + call CheckDefFailure(['for i In range(5)'], 'E690:') | |
1036 | + call CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1023:') | |
1037 | + call CheckScriptFailure(['def Func(arg)', 'for arg in range(5)', 'enddef'], 'E1006:') | |
1038 | + call CheckDefFailure(['for i in "text"'], 'E1024:') | |
1039 | +enddef | |
1040 | + | |
1032 | 1041 | def Test_interrupt_loop() |
1033 | 1042 | let caught = false |
1034 | 1043 | let x = 0 |
@@ -739,6 +739,8 @@ | ||
739 | 739 | static int included_patches[] = |
740 | 740 | { /* Add new patch number below this line */ |
741 | 741 | /**/ |
742 | + 487, | |
743 | +/**/ | |
742 | 744 | 486, |
743 | 745 | /**/ |
744 | 746 | 485, |
@@ -57,6 +57,7 @@ | ||
57 | 57 | ISN_DCALL, // call def function isn_arg.dfunc |
58 | 58 | ISN_UCALL, // call user function or funcref/partial isn_arg.ufunc |
59 | 59 | ISN_PCALL, // call partial, use isn_arg.pfunc |
60 | + ISN_PCALL_END, // cleanup after ISN_PCALL with cpf_top set | |
60 | 61 | ISN_RETURN, // return, result is on top of stack |
61 | 62 | ISN_FUNCREF, // push a function ref to dfunc isn_arg.number |
62 | 63 |
@@ -256,7 +257,7 @@ | ||
256 | 257 | // Functions defined with :def are stored in this growarray. |
257 | 258 | // They are never removed, so that they can be found by index. |
258 | 259 | // Deleted functions have the df_deleted flag set. |
259 | -garray_T def_functions = {0, 0, sizeof(dfunc_T), 50, NULL}; | |
260 | +garray_T def_functions = {0, 0, sizeof(dfunc_T), 200, NULL}; | |
260 | 261 | #else |
261 | 262 | extern garray_T def_functions; |
262 | 263 | #endif |
@@ -1196,6 +1196,11 @@ | ||
1196 | 1196 | // drop the funcref/partial, get back the return value |
1197 | 1197 | ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any; |
1198 | 1198 | |
1199 | + // If partial is above the arguments it must be cleared and replaced with | |
1200 | + // the return value. | |
1201 | + if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL) | |
1202 | + return FAIL; | |
1203 | + | |
1199 | 1204 | return OK; |
1200 | 1205 | } |
1201 | 1206 |
@@ -5200,7 +5205,7 @@ | ||
5200 | 5205 | p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@') |
5201 | 5206 | ? ea.cmd + 1 : ea.cmd; |
5202 | 5207 | p = to_name_end(p, TRUE); |
5203 | - if ((p > ea.cmd && *p != NUL) || *p == '(') | |
5208 | + if (p > ea.cmd && *p != NUL) | |
5204 | 5209 | { |
5205 | 5210 | int oplen; |
5206 | 5211 | int heredoc; |
@@ -5538,6 +5543,7 @@ | ||
5538 | 5543 | case ISN_OPFLOAT: |
5539 | 5544 | case ISN_OPANY: |
5540 | 5545 | case ISN_PCALL: |
5546 | + case ISN_PCALL_END: | |
5541 | 5547 | case ISN_PUSHF: |
5542 | 5548 | case ISN_PUSHNR: |
5543 | 5549 | case ISN_PUSHBOOL: |
@@ -345,7 +345,7 @@ | ||
345 | 345 | static int |
346 | 346 | call_partial(typval_T *tv, int argcount, ectx_T *ectx) |
347 | 347 | { |
348 | - char_u *name; | |
348 | + char_u *name = NULL; | |
349 | 349 | int called_emsg_before = called_emsg; |
350 | 350 | |
351 | 351 | if (tv->v_type == VAR_PARTIAL) |
@@ -356,9 +356,9 @@ | ||
356 | 356 | return call_ufunc(pt->pt_func, argcount, ectx, NULL); |
357 | 357 | name = pt->pt_name; |
358 | 358 | } |
359 | - else | |
359 | + else if (tv->v_type == VAR_FUNC) | |
360 | 360 | name = tv->vval.v_string; |
361 | - if (call_by_name(name, argcount, ectx, NULL) == FAIL) | |
361 | + if (name == NULL || call_by_name(name, argcount, ectx, NULL) == FAIL) | |
362 | 362 | { |
363 | 363 | if (called_emsg == called_emsg_before) |
364 | 364 | semsg(_(e_unknownfunc), name); |
@@ -421,7 +421,6 @@ | ||
421 | 421 | typval_T *tv; |
422 | 422 | int idx; |
423 | 423 | int ret = FAIL; |
424 | - dfunc_T *dfunc; | |
425 | 424 | int defcount = ufunc->uf_args.ga_len - argc; |
426 | 425 | |
427 | 426 | // Get pointer to item in the stack. |
@@ -467,13 +466,17 @@ | ||
467 | 466 | ++ectx.ec_stack.ga_len; |
468 | 467 | } |
469 | 468 | |
470 | - // Reserve space for local variables. | |
471 | - dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; | |
472 | - for (idx = 0; idx < dfunc->df_varcount; ++idx) | |
473 | - STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; | |
474 | - ectx.ec_stack.ga_len += dfunc->df_varcount; | |
469 | + { | |
470 | + // Reserve space for local variables. | |
471 | + dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) | |
472 | + + ufunc->uf_dfunc_idx; | |
475 | 473 | |
476 | - ectx.ec_instr = dfunc->df_instr; | |
474 | + for (idx = 0; idx < dfunc->df_varcount; ++idx) | |
475 | + STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; | |
476 | + ectx.ec_stack.ga_len += dfunc->df_varcount; | |
477 | + | |
478 | + ectx.ec_instr = dfunc->df_instr; | |
479 | + } | |
477 | 480 | |
478 | 481 | // Decide where to start execution, handles optional arguments. |
479 | 482 | init_instr_idx(ufunc, argc, &ectx); |
@@ -1022,16 +1025,16 @@ | ||
1022 | 1025 | clear_tv(&partial); |
1023 | 1026 | if (r == FAIL) |
1024 | 1027 | goto failed; |
1028 | + } | |
1029 | + break; | |
1025 | 1030 | |
1026 | - if (pfunc->cpf_top) | |
1027 | - { | |
1028 | - // Get the funcref from the stack, overwrite with the | |
1029 | - // return value. | |
1030 | - clear_tv(tv); | |
1031 | - --ectx.ec_stack.ga_len; | |
1032 | - *STACK_TV_BOT(-1) = *STACK_TV_BOT(0); | |
1033 | - } | |
1034 | - } | |
1031 | + case ISN_PCALL_END: | |
1032 | + // PCALL finished, arguments have been consumed and replaced by | |
1033 | + // the return value. Now clear the funcref from the stack, | |
1034 | + // and move the return value in its place. | |
1035 | + --ectx.ec_stack.ga_len; | |
1036 | + clear_tv(STACK_TV_BOT(-1)); | |
1037 | + *STACK_TV_BOT(-1) = *STACK_TV_BOT(0); | |
1035 | 1038 | break; |
1036 | 1039 | |
1037 | 1040 | // call a user defined function or funcref/partial |
@@ -1078,6 +1081,7 @@ | ||
1078 | 1081 | case ISN_FUNCREF: |
1079 | 1082 | { |
1080 | 1083 | partial_T *pt = NULL; |
1084 | + dfunc_T *dfunc; | |
1081 | 1085 | |
1082 | 1086 | pt = ALLOC_CLEAR_ONE(partial_T); |
1083 | 1087 | if (pt == NULL) |
@@ -2005,6 +2009,9 @@ | ||
2005 | 2009 | cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount); |
2006 | 2010 | } |
2007 | 2011 | break; |
2012 | + case ISN_PCALL_END: | |
2013 | + smsg("%4d PCALL end", current); | |
2014 | + break; | |
2008 | 2015 | case ISN_RETURN: |
2009 | 2016 | smsg("%4d RETURN", current); |
2010 | 2017 | break; |