To: vim_dev@googlegroups.com Subject: Patch 8.2.2721 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2721 Problem: Vim9: cannot have a linebreak inside a lambda. Solution: Compile the expression before the arguments. Files: src/vim9compile.c, src/testdir/test_vim9_expr.vim *** ../vim-8.2.2720/src/vim9compile.c 2021-04-05 17:11:11.093726064 +0200 --- src/vim9compile.c 2021-04-05 19:34:28.940626689 +0200 *************** *** 3975,3997 **** if (**arg == '(') { int argcount = 1; ! char_u *expr; ! garray_T *stack; type_T *type; // Funcref call: list->(Refs[2])(arg) // or lambda: list->((arg) => expr)(arg) ! // Fist compile the arguments. ! expr = *arg; ! *arg = skipwhite(*arg + 1); ! skip_expr_cctx(arg, cctx); ! *arg = skipwhite(*arg); ! if (**arg != ')') ! { ! semsg(_(e_missing_paren), *arg); return FAIL; ! } ! ++*arg; if (**arg != '(') { if (*skipwhite(*arg) == '(') --- 3975,3999 ---- if (**arg == '(') { int argcount = 1; ! garray_T *stack = &cctx->ctx_type_stack; ! int type_idx_start = stack->ga_len; type_T *type; + int expr_isn_start = cctx->ctx_instr.ga_len; + int expr_isn_end; + int arg_isn_count; // Funcref call: list->(Refs[2])(arg) // or lambda: list->((arg) => expr)(arg) ! // ! // Fist compile the function expression. ! if (compile_parenthesis(arg, cctx, ppconst) == FAIL) return FAIL; ! ! // 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 != '(') { if (*skipwhite(*arg) == '(') *************** *** 4000,4015 **** semsg(_(e_missing_paren), *arg); return FAIL; } - *arg = skipwhite(*arg + 1); if (compile_arguments(arg, cctx, &argcount) == FAIL) return FAIL; ! // Compile the function expression. ! if (compile_parenthesis(&expr, cctx, ppconst) == FAIL) ! return FAIL; ! stack = &cctx->ctx_type_stack; type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; if (generate_PCALL(cctx, argcount, (char_u *)"[expression]", type, FALSE) == FAIL) --- 4002,4044 ---- semsg(_(e_missing_paren), *arg); return FAIL; } *arg = skipwhite(*arg + 1); if (compile_arguments(arg, cctx, &argcount) == FAIL) return FAIL; ! // Move the instructions for the arguments to before the ! // instructions of the expression and move the type of the ! // expression after the argument types. This is what ISN_PCALL ! // expects. stack = &cctx->ctx_type_stack; + arg_isn_count = cctx->ctx_instr.ga_len - expr_isn_end; + if (arg_isn_count > 0) + { + int expr_isn_count = expr_isn_end - expr_isn_start; + isn_T *isn = ALLOC_MULT(isn_T, expr_isn_count); + + if (isn == NULL) + return FAIL; + mch_memmove(isn, ((isn_T *)cctx->ctx_instr.ga_data) + + expr_isn_start, + sizeof(isn_T) * expr_isn_count); + mch_memmove(((isn_T *)cctx->ctx_instr.ga_data) + + expr_isn_start, + ((isn_T *)cctx->ctx_instr.ga_data) + expr_isn_end, + sizeof(isn_T) * arg_isn_count); + mch_memmove(((isn_T *)cctx->ctx_instr.ga_data) + + expr_isn_start + arg_isn_count, + isn, sizeof(isn_T) * expr_isn_count); + vim_free(isn); + + type = ((type_T **)stack->ga_data)[type_idx_start]; + mch_memmove(((type_T **)stack->ga_data) + type_idx_start, + ((type_T **)stack->ga_data) + type_idx_start + 1, + sizeof(type_T *) + * (stack->ga_len - type_idx_start - 1)); + ((type_T **)stack->ga_data)[stack->ga_len - 1] = type; + } + type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; if (generate_PCALL(cctx, argcount, (char_u *)"[expression]", type, FALSE) == FAIL) *** ../vim-8.2.2720/src/testdir/test_vim9_expr.vim 2021-04-05 13:36:30.155371201 +0200 --- src/testdir/test_vim9_expr.vim 2021-04-05 19:35:39.968477986 +0200 *************** *** 2075,2090 **** enddef def Test_expr7_lambda_vim9script() - # TODO: make this work in a :def function var lines =<< trim END - vim9script var v = 10->((a) => a + 2 )() assert_equal(12, v) END ! CheckScriptSuccess(lines) # nested lambda with line breaks lines =<< trim END --- 2075,2088 ---- enddef def Test_expr7_lambda_vim9script() var lines =<< trim END var v = 10->((a) => a + 2 )() assert_equal(12, v) END ! CheckDefAndScriptSuccess(lines) # nested lambda with line breaks lines =<< trim END *** ../vim-8.2.2720/src/version.c 2021-04-05 18:20:42.024142486 +0200 --- src/version.c 2021-04-05 19:36:46.704334790 +0200 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2721, /**/ -- hundred-and-one symptoms of being an internet addict: 65. The last time you looked at the clock it was 11:30pm, and in what seems like only a few seconds later, your sister runs past you to catch her 7am school bus. /// 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 ///