Mercurial > vim
comparison src/eval.c @ 17612:e259d11e2900 v8.1.1803
patch 8.1.1803: all builtin functions are global
commit https://github.com/vim/vim/commit/ac92e25a33c37ec5becbfffeccda136c73b761ac
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Aug 3 21:58:38 2019 +0200
patch 8.1.1803: all builtin functions are global
Problem: All builtin functions are global.
Solution: Add the method call operator ->. Implemented for a limited number
of functions.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 03 Aug 2019 22:00:07 +0200 |
parents | ff097edaae89 |
children | 9ffec4eb8d33 |
comparison
equal
deleted
inserted
replaced
17611:b9a3d542a042 | 17612:e259d11e2900 |
---|---|
4410 * ! in front logical NOT | 4410 * ! in front logical NOT |
4411 * - in front unary minus | 4411 * - in front unary minus |
4412 * + in front unary plus (ignored) | 4412 * + in front unary plus (ignored) |
4413 * trailing [] subscript in String or List | 4413 * trailing [] subscript in String or List |
4414 * trailing .name entry in Dictionary | 4414 * trailing .name entry in Dictionary |
4415 * trailing ->name() method call | |
4415 * | 4416 * |
4416 * "arg" must point to the first non-white of the expression. | 4417 * "arg" must point to the first non-white of the expression. |
4417 * "arg" is advanced to the next non-white after the recognized expression. | 4418 * "arg" is advanced to the next non-white after the recognized expression. |
4418 * | 4419 * |
4419 * Return OK or FAIL. | 4420 * Return OK or FAIL. |
4688 else | 4689 else |
4689 { | 4690 { |
4690 funcexe_T funcexe; | 4691 funcexe_T funcexe; |
4691 | 4692 |
4692 // Invoke the function. | 4693 // Invoke the function. |
4693 funcexe.argv_func = NULL; | 4694 vim_memset(&funcexe, 0, sizeof(funcexe)); |
4694 funcexe.firstline = curwin->w_cursor.lnum; | 4695 funcexe.firstline = curwin->w_cursor.lnum; |
4695 funcexe.lastline = curwin->w_cursor.lnum; | 4696 funcexe.lastline = curwin->w_cursor.lnum; |
4696 funcexe.doesrange = &len; | 4697 funcexe.doesrange = &len; |
4697 funcexe.evaluate = evaluate; | 4698 funcexe.evaluate = evaluate; |
4698 funcexe.partial = partial; | 4699 funcexe.partial = partial; |
4699 funcexe.selfdict = NULL; | |
4700 ret = get_func_tv(s, len, rettv, arg, &funcexe); | 4700 ret = get_func_tv(s, len, rettv, arg, &funcexe); |
4701 } | 4701 } |
4702 vim_free(s); | 4702 vim_free(s); |
4703 | 4703 |
4704 /* If evaluate is FALSE rettv->v_type was not set in | 4704 /* If evaluate is FALSE rettv->v_type was not set in |
4796 rettv->vval.v_number = val; | 4796 rettv->vval.v_number = val; |
4797 } | 4797 } |
4798 } | 4798 } |
4799 } | 4799 } |
4800 | 4800 |
4801 return ret; | |
4802 } | |
4803 | |
4804 /* | |
4805 * Evaluate "->method()". | |
4806 * "*arg" points to the '-'. | |
4807 * Returns FAIL or OK. "*arg" is advanced to after the ')'. | |
4808 */ | |
4809 static int | |
4810 eval_method( | |
4811 char_u **arg, | |
4812 typval_T *rettv, | |
4813 int evaluate, | |
4814 int verbose) /* give error messages */ | |
4815 { | |
4816 char_u *name; | |
4817 long len; | |
4818 funcexe_T funcexe; | |
4819 int ret = OK; | |
4820 typval_T base = *rettv; | |
4821 | |
4822 // Skip over the ->. | |
4823 *arg += 2; | |
4824 | |
4825 // Locate the method name. | |
4826 name = *arg; | |
4827 for (len = 0; ASCII_ISALNUM(name[len]) || name[len] == '_'; ++len) | |
4828 ; | |
4829 if (len == 0) | |
4830 { | |
4831 if (verbose) | |
4832 emsg(_("E260: Missing name after ->")); | |
4833 return FAIL; | |
4834 } | |
4835 | |
4836 // Check for the "(". Skip over white space after it. | |
4837 if (name[len] != '(') | |
4838 { | |
4839 if (verbose) | |
4840 semsg(_(e_missingparen), name); | |
4841 return FAIL; | |
4842 } | |
4843 *arg += len; | |
4844 | |
4845 vim_memset(&funcexe, 0, sizeof(funcexe)); | |
4846 funcexe.evaluate = evaluate; | |
4847 funcexe.basetv = &base; | |
4848 rettv->v_type = VAR_UNKNOWN; | |
4849 ret = get_func_tv(name, len, rettv, arg, &funcexe); | |
4850 | |
4851 /* Clear the funcref afterwards, so that deleting it while | |
4852 * evaluating the arguments is possible (see test55). */ | |
4853 if (evaluate) | |
4854 clear_tv(&base); | |
4855 | |
4856 /* Stop the expression evaluation when immediately aborting on | |
4857 * error, or when an interrupt occurred or an exception was thrown | |
4858 * but not caught. */ | |
4859 if (aborting()) | |
4860 { | |
4861 if (ret == OK) | |
4862 clear_tv(rettv); | |
4863 ret = FAIL; | |
4864 } | |
4801 return ret; | 4865 return ret; |
4802 } | 4866 } |
4803 | 4867 |
4804 /* | 4868 /* |
4805 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key". | 4869 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key". |
7357 | 7421 |
7358 name[len] = cc; | 7422 name[len] = cc; |
7359 } | 7423 } |
7360 | 7424 |
7361 /* | 7425 /* |
7362 * Handle expr[expr], expr[expr:expr] subscript and .name lookup. | 7426 * Handle: |
7363 * Also handle function call with Funcref variable: func(expr) | 7427 * - expr[expr], expr[expr:expr] subscript |
7364 * Can all be combined: dict.func(expr)[idx]['func'](expr) | 7428 * - ".name" lookup |
7429 * - function call with Funcref variable: func(expr) | |
7430 * - method call: var->method() | |
7431 * | |
7432 * Can all be combined in any order: dict.func(expr)[idx]['func'](expr)->len() | |
7365 */ | 7433 */ |
7366 int | 7434 int |
7367 handle_subscript( | 7435 handle_subscript( |
7368 char_u **arg, | 7436 char_u **arg, |
7369 typval_T *rettv, | 7437 typval_T *rettv, |
7376 typval_T functv; | 7444 typval_T functv; |
7377 | 7445 |
7378 // "." is ".name" lookup when we found a dict or when evaluating and | 7446 // "." is ".name" lookup when we found a dict or when evaluating and |
7379 // scriptversion is at least 2, where string concatenation is "..". | 7447 // scriptversion is at least 2, where string concatenation is "..". |
7380 while (ret == OK | 7448 while (ret == OK |
7381 && (**arg == '[' | 7449 && (((**arg == '[' |
7382 || (**arg == '.' && (rettv->v_type == VAR_DICT | 7450 || (**arg == '.' && (rettv->v_type == VAR_DICT |
7383 || (!evaluate | 7451 || (!evaluate |
7384 && (*arg)[1] != '.' | 7452 && (*arg)[1] != '.' |
7385 && current_sctx.sc_version >= 2))) | 7453 && current_sctx.sc_version >= 2))) |
7386 || (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC | 7454 || (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC |
7387 || rettv->v_type == VAR_PARTIAL))) | 7455 || rettv->v_type == VAR_PARTIAL))) |
7388 && !VIM_ISWHITE(*(*arg - 1))) | 7456 && !VIM_ISWHITE(*(*arg - 1))) |
7457 || (**arg == '-' && (*arg)[1] == '>'))) | |
7389 { | 7458 { |
7390 if (**arg == '(') | 7459 if (**arg == '(') |
7391 { | 7460 { |
7392 partial_T *pt = NULL; | 7461 partial_T *pt = NULL; |
7393 funcexe_T funcexe; | 7462 funcexe_T funcexe; |
7408 s = functv.vval.v_string; | 7477 s = functv.vval.v_string; |
7409 } | 7478 } |
7410 else | 7479 else |
7411 s = (char_u *)""; | 7480 s = (char_u *)""; |
7412 | 7481 |
7413 funcexe.argv_func = NULL; | 7482 vim_memset(&funcexe, 0, sizeof(funcexe)); |
7414 funcexe.firstline = curwin->w_cursor.lnum; | 7483 funcexe.firstline = curwin->w_cursor.lnum; |
7415 funcexe.lastline = curwin->w_cursor.lnum; | 7484 funcexe.lastline = curwin->w_cursor.lnum; |
7416 funcexe.doesrange = NULL; | |
7417 funcexe.evaluate = evaluate; | 7485 funcexe.evaluate = evaluate; |
7418 funcexe.partial = pt; | 7486 funcexe.partial = pt; |
7419 funcexe.selfdict = selfdict; | 7487 funcexe.selfdict = selfdict; |
7420 ret = get_func_tv(s, -1, rettv, arg, &funcexe); | 7488 ret = get_func_tv(s, -1, rettv, arg, &funcexe); |
7421 | 7489 |
7433 clear_tv(rettv); | 7501 clear_tv(rettv); |
7434 ret = FAIL; | 7502 ret = FAIL; |
7435 } | 7503 } |
7436 dict_unref(selfdict); | 7504 dict_unref(selfdict); |
7437 selfdict = NULL; | 7505 selfdict = NULL; |
7506 } | |
7507 else if (**arg == '-') | |
7508 { | |
7509 if (eval_method(arg, rettv, evaluate, verbose) == FAIL) | |
7510 { | |
7511 clear_tv(rettv); | |
7512 ret = FAIL; | |
7513 } | |
7438 } | 7514 } |
7439 else /* **arg == '[' || **arg == '.' */ | 7515 else /* **arg == '[' || **arg == '.' */ |
7440 { | 7516 { |
7441 dict_unref(selfdict); | 7517 dict_unref(selfdict); |
7442 if (rettv->v_type == VAR_DICT) | 7518 if (rettv->v_type == VAR_DICT) |