Mercurial > vim
diff src/vim9cmds.c @ 30065:6cf788ab844c v9.0.0370
patch 9.0.0370: cleaning up afterwards can make a function messy
Commit: https://github.com/vim/vim/commit/1d84f7608f1e41dad03b8cc7925895437775f7c0
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Sep 3 21:35:53 2022 +0100
patch 9.0.0370: cleaning up afterwards can make a function messy
Problem: Cleaning up afterwards can make a function messy.
Solution: Add the :defer command.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 03 Sep 2022 22:45:03 +0200 |
parents | d269dd3cd31d |
children | a542dfb1c1a2 |
line wrap: on
line diff
--- a/src/vim9cmds.c +++ b/src/vim9cmds.c @@ -1654,6 +1654,9 @@ compile_throw(char_u *arg, cctx_T *cctx return p; } +/* + * Compile an expression or function call. + */ char_u * compile_eval(char_u *arg, cctx_T *cctx) { @@ -1682,6 +1685,67 @@ compile_eval(char_u *arg, cctx_T *cctx) } /* + * Compile "defer func(arg)". + */ + char_u * +compile_defer(char_u *arg_start, cctx_T *cctx) +{ + char_u *p; + char_u *arg = arg_start; + int argcount = 0; + dfunc_T *dfunc; + type_T *type; + int func_idx; + + // Get a funcref for the function name. + // TODO: better way to find the "(". + p = vim_strchr(arg, '('); + if (p == NULL) + { + semsg(_(e_missing_parenthesis_str), arg); + return NULL; + } + *p = NUL; + func_idx = find_internal_func(arg); + if (func_idx >= 0) + // TODO: better type + generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx), + &t_func_any, FALSE); + else if (compile_expr0(&arg, cctx) == FAIL) + return NULL; + *p = '('; + + // check for function type + type = get_type_on_stack(cctx, 0); + if (type->tt_type != VAR_FUNC) + { + emsg(_(e_function_name_required)); + return NULL; + } + + // compile the arguments + arg = skipwhite(p + 1); + if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL) + return NULL; + + // TODO: check argument count with "type" + + dfunc = ((dfunc_T *)def_functions.ga_data) + cctx->ctx_ufunc->uf_dfunc_idx; + if (dfunc->df_defer_var_idx == 0) + { + lvar_T *lvar = reserve_local(cctx, (char_u *)"@defer@", 7, + TRUE, &t_list_any); + if (lvar == NULL) + return NULL; + dfunc->df_defer_var_idx = lvar->lv_idx + 1; + } + if (generate_DEFER(cctx, dfunc->df_defer_var_idx - 1, argcount) == FAIL) + return NULL; + + return skipwhite(arg); +} + +/* * compile "echo expr" * compile "echomsg expr" * compile "echoerr expr"