To: vim_dev@googlegroups.com Subject: Patch 8.2.4124 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.4124 Problem: Vim9: method in compiled function may not see script item. Solution: Make sure not to skip to the next line. (closes #9496) Files: src/vim9expr.c, src/testdir/test_vim9_expr.vim *** ../vim-8.2.4123/src/vim9expr.c 2022-01-16 20:59:32.429613796 +0000 --- src/vim9expr.c 2022-01-17 20:44:48.803480942 +0000 *************** *** 1732,1752 **** } else { *paren = NUL; ! if (compile_expr8(arg, cctx, ppconst) == FAIL ! || *skipwhite(*arg) != NUL) { - *paren = '('; semsg(_(e_invalid_expression_str), pstart); return FAIL; } - *paren = '('; } - // Remember the next instruction index, where the instructions - // for arguments are being written. - expr_isn_end = cctx->ctx_instr.ga_len; - // Compile the arguments. if (**arg != '(') { --- 1732,1754 ---- } else { + int fail; + int save_len = cctx->ctx_ufunc->uf_lines.ga_len; + *paren = NUL; ! // do not look in the next line ! cctx->ctx_ufunc->uf_lines.ga_len = 1; ! fail = compile_expr8(arg, cctx, ppconst) == FAIL ! || *skipwhite(*arg) != NUL; ! *paren = '('; ! cctx->ctx_ufunc->uf_lines.ga_len = save_len; ! if (fail) { semsg(_(e_invalid_expression_str), pstart); return FAIL; } } // Compile the arguments. if (**arg != '(') { *************** *** 1756,1761 **** --- 1758,1768 ---- semsg(_(e_missing_parenthesis_str), *arg); return FAIL; } + + // Remember the next instruction index, where the instructions + // for arguments are being written. + expr_isn_end = cctx->ctx_instr.ga_len; + *arg = skipwhite(*arg + 1); if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL) return FAIL; *** ../vim-8.2.4123/src/testdir/test_vim9_expr.vim 2022-01-16 20:59:32.429613796 +0000 --- src/testdir/test_vim9_expr.vim 2022-01-17 20:47:18.475181420 +0000 *************** *** 1717,1723 **** let $TESTVAR = 'testvar' " type casts ! def Test_expr7t() var lines =<< trim END var ls: list = ['a', g:string_empty] var ln: list = [g:anint, g:thefour] --- 1717,1723 ---- let $TESTVAR = 'testvar' " type casts ! def Test_expr7() var lines =<< trim END var ls: list = ['a', g:string_empty] var ln: list = [g:anint, g:thefour] *************** *** 1743,1749 **** enddef " test low level expression ! def Test_expr7_number() # number constant var lines =<< trim END assert_equal(0, 0) --- 1743,1749 ---- enddef " test low level expression ! def Test_expr8_number() # number constant var lines =<< trim END assert_equal(0, 0) *************** *** 1756,1762 **** CheckDefAndScriptSuccess(lines) enddef ! def Test_expr7_float() # float constant if !has('float') MissingFeature 'float' --- 1756,1762 ---- CheckDefAndScriptSuccess(lines) enddef ! def Test_expr8_float() # float constant if !has('float') MissingFeature 'float' *************** *** 1771,1777 **** endif enddef ! def Test_expr7_blob() # blob constant var lines =<< trim END assert_equal(g:blob_empty, 0z) --- 1771,1777 ---- endif enddef ! def Test_expr8_blob() # blob constant var lines =<< trim END assert_equal(g:blob_empty, 0z) *************** *** 1803,1809 **** CheckDefAndScriptFailure(["var x = 0z123"], 'E973:', 1) enddef ! def Test_expr7_string() # string constant var lines =<< trim END assert_equal(g:string_empty, '') --- 1803,1809 ---- CheckDefAndScriptFailure(["var x = 0z123"], 'E973:', 1) enddef ! def Test_expr8_string() # string constant var lines =<< trim END assert_equal(g:string_empty, '') *************** *** 1820,1826 **** CheckDefAndScriptFailure(["var x = 'abc"], 'E115:', 1) enddef ! def Test_expr7_vimvar() v:errors = [] var errs: list = v:errors CheckDefFailure(['var errs: list = v:errors'], 'E1012:') --- 1820,1826 ---- CheckDefAndScriptFailure(["var x = 'abc"], 'E115:', 1) enddef ! def Test_expr8_vimvar() v:errors = [] var errs: list = v:errors CheckDefFailure(['var errs: list = v:errors'], 'E1012:') *************** *** 1845,1851 **** bwipe! enddef ! def Test_expr7_special() # special constant var lines =<< trim END assert_equal(g:special_true, true) --- 1845,1851 ---- bwipe! enddef ! def Test_expr8_special() # special constant var lines =<< trim END assert_equal(g:special_true, true) *************** *** 1882,1888 **** CheckDefAndScriptFailure(['v:none = 22'], 'E46:', 1) enddef ! def Test_expr7_list() # list var lines =<< trim END assert_equal(g:list_empty, []) --- 1882,1888 ---- CheckDefAndScriptFailure(['v:none = 22'], 'E46:', 1) enddef ! def Test_expr8_list() # list var lines =<< trim END assert_equal(g:list_empty, []) *************** *** 1955,1961 **** CheckDefAndScriptFailure(lines + ['echo numbers[a :b]'], 'E1004:', 4) enddef ! def Test_expr7_list_vim9script() var lines =<< trim END var l = [ 11, --- 1955,1961 ---- CheckDefAndScriptFailure(lines + ['echo numbers[a :b]'], 'E1004:', 4) enddef ! def Test_expr8_list_vim9script() var lines =<< trim END var l = [ 11, *************** *** 2043,2049 **** x == 2 enddef ! def Test_expr7_lambda() var lines =<< trim END var La = () => 'result' # comment --- 2043,2049 ---- x == 2 enddef ! def Test_expr8_lambda() var lines =<< trim END var La = () => 'result' # comment *************** *** 2129,2135 **** CheckDefAndScriptSuccess(lines) enddef ! def Test_expr7_lambda_block() var lines =<< trim END var Func = (s: string): string => { return 'hello ' .. s --- 2129,2135 ---- CheckDefAndScriptSuccess(lines) enddef ! def Test_expr8_lambda_block() var lines =<< trim END var Func = (s: string): string => { return 'hello ' .. s *************** *** 2209,2215 **** x == 2 enddef ! def Test_expr7_new_lambda() var lines =<< trim END var La = () => 'result' assert_equal('result', La()) --- 2209,2215 ---- x == 2 enddef ! def Test_expr8_new_lambda() var lines =<< trim END var La = () => 'result' assert_equal('result', La()) *************** *** 2294,2300 **** CheckDefAndScriptFailure(['var Fx = (a) => [0', ' 1]'], 'E696:', 2) enddef ! def Test_expr7_lambda_vim9script() var lines =<< trim END var v = 10->((a) => a --- 2294,2300 ---- CheckDefAndScriptFailure(['var Fx = (a) => [0', ' 1]'], 'E696:', 2) enddef ! def Test_expr8_lambda_vim9script() var lines =<< trim END var v = 10->((a) => a *************** *** 2313,2319 **** CheckDefAndScriptSuccess(lines) enddef ! def Test_expr7_funcref() var lines =<< trim END def RetNumber(): number return 123 --- 2313,2319 ---- CheckDefAndScriptSuccess(lines) enddef ! def Test_expr8_funcref() var lines =<< trim END def RetNumber(): number return 123 *************** *** 2350,2356 **** let g:test_space_dict = {'': 'empty', ' ': 'space'} let g:test_hash_dict = #{one: 1, two: 2} ! def Test_expr7_dict() # dictionary var lines =<< trim END assert_equal(g:dict_empty, {}) --- 2350,2356 ---- let g:test_space_dict = {'': 'empty', ' ': 'space'} let g:test_hash_dict = #{one: 1, two: 2} ! def Test_expr8_dict() # dictionary var lines =<< trim END assert_equal(g:dict_empty, {}) *************** *** 2461,2467 **** CheckDefExecAndScriptFailure(['{}[getftype("file")]'], 'E716: Key not present in Dictionary: ""', 1) enddef ! def Test_expr7_dict_vim9script() var lines =<< trim END var d = { ['one']: --- 2461,2467 ---- CheckDefExecAndScriptFailure(['{}[getftype("file")]'], 'E716: Key not present in Dictionary: ""', 1) enddef ! def Test_expr8_dict_vim9script() var lines =<< trim END var d = { ['one']: *************** *** 2592,2598 **** CheckScriptSuccess(lines) enddef ! def Test_expr7_dict_in_block() var lines =<< trim END vim9script command MyCommand { --- 2592,2598 ---- CheckScriptSuccess(lines) enddef ! def Test_expr8_dict_in_block() var lines =<< trim END vim9script command MyCommand { *************** *** 2615,2621 **** delcommand YourCommand enddef ! def Test_expr7_call_2bool() var lines =<< trim END vim9script --- 2615,2621 ---- delcommand YourCommand enddef ! def Test_expr8_call_2bool() var lines =<< trim END vim9script *************** *** 2663,2669 **** CheckDefExecAndScriptFailure(["var d: dict", "d = g:list_empty"], 'E1012: Type mismatch; expected dict but got list', 2) enddef ! def Test_expr7_any_index_slice() var lines =<< trim END # getting the one member should clear the list only after getting the item assert_equal('bbb', ['aaa', 'bbb', 'ccc'][1]) --- 2663,2669 ---- CheckDefExecAndScriptFailure(["var d: dict", "d = g:list_empty"], 'E1012: Type mismatch; expected dict but got list', 2) enddef ! def Test_expr8_any_index_slice() var lines =<< trim END # getting the one member should clear the list only after getting the item assert_equal('bbb', ['aaa', 'bbb', 'ccc'][1]) *************** *** 2817,2823 **** b:someVar = &fdm enddef ! def Test_expr7_option() var lines =<< trim END # option set ts=11 --- 2817,2823 ---- b:someVar = &fdm enddef ! def Test_expr8_option() var lines =<< trim END # option set ts=11 *************** *** 2844,2850 **** CheckDefAndScriptSuccess(lines) enddef ! def Test_expr7_environment() var lines =<< trim END # environment variable assert_equal('testvar', $TESTVAR) --- 2844,2850 ---- CheckDefAndScriptSuccess(lines) enddef ! def Test_expr8_environment() var lines =<< trim END # environment variable assert_equal('testvar', $TESTVAR) *************** *** 2856,2862 **** CheckDefAndScriptFailure(["$"], ['E1002:', 'E15:'], 1) enddef ! def Test_expr7_register() var lines =<< trim END @a = 'register a' assert_equal('register a', @a) --- 2856,2862 ---- CheckDefAndScriptFailure(["$"], ['E1002:', 'E15:'], 1) enddef ! def Test_expr8_register() var lines =<< trim END @a = 'register a' assert_equal('register a', @a) *************** *** 2882,2888 **** enddef " This is slow when run under valgrind. ! def Test_expr7_namespace() var lines =<< trim END g:some_var = 'some' assert_equal('some', get(g:, 'some_var')) --- 2882,2888 ---- enddef " This is slow when run under valgrind. ! def Test_expr8_namespace() var lines =<< trim END g:some_var = 'some' assert_equal('some', get(g:, 'some_var')) *************** *** 2911,2917 **** CheckDefAndScriptSuccess(lines) enddef ! def Test_expr7_namespace_loop_def() var lines =<< trim END # check using g: in a for loop more than DO_NOT_FREE_CNT times var exists = 0 --- 2911,2917 ---- CheckDefAndScriptSuccess(lines) enddef ! def Test_expr8_namespace_loop_def() var lines =<< trim END # check using g: in a for loop more than DO_NOT_FREE_CNT times var exists = 0 *************** *** 2930,2937 **** enddef " NOTE: this is known to be slow. To skip use: ! " :let $TEST_SKIP_PAT = 'Test_expr7_namespace_loop_script' ! def Test_expr7_namespace_loop_script() var lines =<< trim END vim9script # check using g: in a for loop more than DO_NOT_FREE_CNT times --- 2930,2937 ---- enddef " NOTE: this is known to be slow. To skip use: ! " :let $TEST_SKIP_PAT = 'Test_expr8_namespace_loop_script' ! def Test_expr8_namespace_loop_script() var lines =<< trim END vim9script # check using g: in a for loop more than DO_NOT_FREE_CNT times *************** *** 2950,2956 **** CheckScriptSuccess(lines) enddef ! def Test_expr7_parens() # (expr) var lines =<< trim END assert_equal(4, (6 * 4) / 6) --- 2950,2956 ---- CheckScriptSuccess(lines) enddef ! def Test_expr8_parens() # (expr) var lines =<< trim END assert_equal(4, (6 * 4) / 6) *************** *** 2982,2988 **** CheckDefAndScriptSuccess(lines) enddef ! def Test_expr7_negate_add() var lines =<< trim END assert_equal(-99, -99) assert_equal(-99, - 99) --- 2982,2988 ---- CheckDefAndScriptSuccess(lines) enddef ! def Test_expr8_negate_add() var lines =<< trim END assert_equal(-99, -99) assert_equal(-99, - 99) *************** *** 3031,3037 **** legacy return #{key: 'ok'}.key enddef ! def Test_expr7_legacy_script() var lines =<< trim END let s:legacy = 'legacy' def GetLocal(): string --- 3031,3037 ---- legacy return #{key: 'ok'}.key enddef ! def Test_expr8_legacy_script() var lines =<< trim END let s:legacy = 'legacy' def GetLocal(): string *************** *** 3065,3071 **** return arg enddef ! def Test_expr7_call() var lines =<< trim END assert_equal('yes', 'yes'->Echo()) assert_equal(true, !range(5)->empty()) --- 3065,3071 ---- return arg enddef ! def Test_expr8_call() var lines =<< trim END assert_equal('yes', 'yes'->Echo()) assert_equal(true, !range(5)->empty()) *************** *** 3098,3104 **** delete('Xruntime', 'rf') enddef ! def Test_expr7_method_call() var lines =<< trim END new setline(1, ['first', 'last']) --- 3098,3104 ---- delete('Xruntime', 'rf') enddef ! def Test_expr8_method_call() var lines =<< trim END new setline(1, ['first', 'last']) *************** *** 3175,3181 **** CheckDefExecFailure(lines, 'E1013:') enddef ! def Test_expr7_method_call_linebreak() # this was giving an error when skipping over the expression var lines =<< trim END vim9script --- 3175,3181 ---- CheckDefExecFailure(lines, 'E1013:') enddef ! def Test_expr8_method_call_linebreak() # this was giving an error when skipping over the expression var lines =<< trim END vim9script *************** *** 3191,3198 **** CheckScriptSuccess(lines) enddef ! def Test_expr7_not() var lines =<< trim END assert_equal(true, !'') assert_equal(true, ![]) --- 3191,3224 ---- CheckScriptSuccess(lines) enddef + def Test_expr8_method_call_import() + var lines =<< trim END + vim9script + export def Square(items: list): list + return map(items, (_, i) => i * i) + enddef + END + call writefile(lines, 'Xsquare.vim') + + lines =<< trim END + vim9script + import './Xsquare.vim' + + def Test(): list + return range(5) + ->Xsquare.Square() + ->map((_, i) => i * 10) + enddef + + assert_equal([0, 10, 40, 90, 160], Test()) + END + CheckScriptSuccess(lines) + + delete('Xsquare.vim') + enddef + ! def Test_expr8_not() var lines =<< trim END assert_equal(true, !'') assert_equal(true, ![]) *************** *** 3244,3250 **** let g:anumber = 42 ! def Test_expr7_negate() var lines =<< trim END var nr = 1 assert_equal(-1, -nr) --- 3270,3276 ---- let g:anumber = 42 ! def Test_expr8_negate() var lines =<< trim END var nr = 1 assert_equal(-1, -nr) *************** *** 3253,3259 **** CheckDefAndScriptSuccess(lines) enddef ! func Test_expr7_fails() call CheckDefFailure(["var x = (12"], "E1097:", 3) call CheckScriptFailure(['vim9script', "var x = (12"], 'E110:', 2) --- 3279,3285 ---- CheckDefAndScriptSuccess(lines) enddef ! func Test_expr8_fails() call CheckDefFailure(["var x = (12"], "E1097:", 3) call CheckScriptFailure(['vim9script', "var x = (12"], 'E110:', 2) *************** *** 3313,3319 **** return a:one .. a:two endfunc ! def Test_expr7_trailing() var lines =<< trim END # user function call assert_equal(123, g:CallMe(123)) --- 3339,3345 ---- return a:one .. a:two endfunc ! def Test_expr8_trailing() var lines =<< trim END # user function call assert_equal(123, g:CallMe(123)) *************** *** 3349,3355 **** CheckDefAndScriptSuccess(lines) enddef ! def Test_expr7_string_subscript() var lines =<< trim END var text = 'abcdef' assert_equal('f', text[-1]) --- 3375,3381 ---- CheckDefAndScriptSuccess(lines) enddef ! def Test_expr8_string_subscript() var lines =<< trim END var text = 'abcdef' assert_equal('f', text[-1]) *************** *** 3448,3454 **** CheckDefAndScriptFailure(lines, ['E1012: Type mismatch; expected number but got string', 'E1030: Using a String as a Number: "2"'], 1) enddef ! def Test_expr7_list_subscript() var lines =<< trim END var list = [0, 1, 2, 3, 4] assert_equal(0, list[0]) --- 3474,3480 ---- CheckDefAndScriptFailure(lines, ['E1012: Type mismatch; expected number but got string', 'E1030: Using a String as a Number: "2"'], 1) enddef ! def Test_expr8_list_subscript() var lines =<< trim END var list = [0, 1, 2, 3, 4] assert_equal(0, list[0]) *************** *** 3491,3497 **** CheckDefAndScriptSuccess(lines) enddef ! def Test_expr7_dict_subscript() var lines =<< trim END var l = [{lnum: 2}, {lnum: 1}] var res = l[0].lnum > l[1].lnum --- 3517,3523 ---- CheckDefAndScriptSuccess(lines) enddef ! def Test_expr8_dict_subscript() var lines =<< trim END var l = [{lnum: 2}, {lnum: 1}] var res = l[0].lnum > l[1].lnum *************** *** 3512,3518 **** CheckDefAndScriptSuccess(lines) enddef ! def Test_expr7_blob_subscript() var lines =<< trim END var b = 0z112233 assert_equal(0x11, b[0]) --- 3538,3544 ---- CheckDefAndScriptSuccess(lines) enddef ! def Test_expr8_blob_subscript() var lines =<< trim END var b = 0z112233 assert_equal(0x11, b[0]) *************** *** 3524,3530 **** CheckDefAndScriptSuccess(lines) enddef ! def Test_expr7_subscript_linebreak() var lines =<< trim END var range = range( 3) --- 3550,3556 ---- CheckDefAndScriptSuccess(lines) enddef ! def Test_expr8_subscript_linebreak() var lines =<< trim END var range = range( 3) *************** *** 3567,3573 **** CheckDefAndScriptFailure(lines, ['E1127:', 'E116:'], 2) enddef ! func Test_expr7_trailing_fails() call CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8))'], 'E107:', 2) call CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8)) ()'], 'E274:', 2) endfunc --- 3593,3599 ---- CheckDefAndScriptFailure(lines, ['E1127:', 'E116:'], 2) enddef ! func Test_expr8_trailing_fails() call CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8))'], 'E107:', 2) call CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8)) ()'], 'E274:', 2) endfunc *** ../vim-8.2.4123/src/version.c 2022-01-17 20:09:02.860881495 +0000 --- src/version.c 2022-01-17 20:29:37.573463180 +0000 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 4124, /**/ -- There are 2 kinds of people in my world: those who know Unix, Perl, Vim, GNU, Linux, etc, and those who know COBOL. It gets very difficult for me at parties, not knowing which group to socialise with :-) Sitaram Chamarty /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///