Mercurial > vim
comparison src/eval.c @ 17646:e5397617d6ca v8.1.1820
patch 8.1.1820: using expr->FuncRef() does not work
commit https://github.com/vim/vim/commit/761fdf01c6e307c448cec2684f8b315ba6d1f454
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Aug 5 23:10:16 2019 +0200
patch 8.1.1820: using expr->FuncRef() does not work
Problem: Using expr->FuncRef() does not work.
Solution: Make FuncRef work as a method.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 05 Aug 2019 23:15:05 +0200 |
parents | 9ffec4eb8d33 |
children | da7890e3359b |
comparison
equal
deleted
inserted
replaced
17645:db112d38c152 | 17646:e5397617d6ca |
---|---|
3653 p_cpo = save_cpo; | 3653 p_cpo = save_cpo; |
3654 return matches; | 3654 return matches; |
3655 } | 3655 } |
3656 | 3656 |
3657 /* | 3657 /* |
3658 * Handle a name followed by "(". Both for just "name(arg)" and for | |
3659 * "expr->name(arg)". | |
3660 * Returns OK or FAIL. | |
3661 */ | |
3662 static int | |
3663 eval_func( | |
3664 char_u **arg, // points to "(", will be advanced | |
3665 char_u *name, | |
3666 int name_len, | |
3667 typval_T *rettv, | |
3668 int evaluate, | |
3669 typval_T *basetv) // "expr" for "expr->name(arg)" | |
3670 { | |
3671 char_u *s = name; | |
3672 int len = name_len; | |
3673 partial_T *partial; | |
3674 int ret = OK; | |
3675 | |
3676 if (!evaluate) | |
3677 check_vars(s, len); | |
3678 | |
3679 /* If "s" is the name of a variable of type VAR_FUNC | |
3680 * use its contents. */ | |
3681 s = deref_func_name(s, &len, &partial, !evaluate); | |
3682 | |
3683 /* Need to make a copy, in case evaluating the arguments makes | |
3684 * the name invalid. */ | |
3685 s = vim_strsave(s); | |
3686 if (s == NULL) | |
3687 ret = FAIL; | |
3688 else | |
3689 { | |
3690 funcexe_T funcexe; | |
3691 | |
3692 // Invoke the function. | |
3693 vim_memset(&funcexe, 0, sizeof(funcexe)); | |
3694 funcexe.firstline = curwin->w_cursor.lnum; | |
3695 funcexe.lastline = curwin->w_cursor.lnum; | |
3696 funcexe.doesrange = &len; | |
3697 funcexe.evaluate = evaluate; | |
3698 funcexe.partial = partial; | |
3699 funcexe.basetv = basetv; | |
3700 ret = get_func_tv(s, len, rettv, arg, &funcexe); | |
3701 } | |
3702 vim_free(s); | |
3703 | |
3704 /* If evaluate is FALSE rettv->v_type was not set in | |
3705 * get_func_tv, but it's needed in handle_subscript() to parse | |
3706 * what follows. So set it here. */ | |
3707 if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') | |
3708 { | |
3709 rettv->vval.v_string = NULL; | |
3710 rettv->v_type = VAR_FUNC; | |
3711 } | |
3712 | |
3713 /* Stop the expression evaluation when immediately | |
3714 * aborting on error, or when an interrupt occurred or | |
3715 * an exception was thrown but not caught. */ | |
3716 if (evaluate && aborting()) | |
3717 { | |
3718 if (ret == OK) | |
3719 clear_tv(rettv); | |
3720 ret = FAIL; | |
3721 } | |
3722 return ret; | |
3723 } | |
3724 | |
3725 /* | |
3658 * The "evaluate" argument: When FALSE, the argument is only parsed but not | 3726 * The "evaluate" argument: When FALSE, the argument is only parsed but not |
3659 * executed. The function may return OK, but the rettv will be of type | 3727 * executed. The function may return OK, but the rettv will be of type |
3660 * VAR_UNKNOWN. The function still returns FAIL for a syntax error. | 3728 * VAR_UNKNOWN. The function still returns FAIL for a syntax error. |
3661 */ | 3729 */ |
3662 | 3730 |
4669 if (len <= 0) | 4737 if (len <= 0) |
4670 ret = FAIL; | 4738 ret = FAIL; |
4671 else | 4739 else |
4672 { | 4740 { |
4673 if (**arg == '(') /* recursive! */ | 4741 if (**arg == '(') /* recursive! */ |
4674 { | 4742 ret = eval_func(arg, s, len, rettv, evaluate, NULL); |
4675 partial_T *partial; | |
4676 | |
4677 if (!evaluate) | |
4678 check_vars(s, len); | |
4679 | |
4680 /* If "s" is the name of a variable of type VAR_FUNC | |
4681 * use its contents. */ | |
4682 s = deref_func_name(s, &len, &partial, !evaluate); | |
4683 | |
4684 /* Need to make a copy, in case evaluating the arguments makes | |
4685 * the name invalid. */ | |
4686 s = vim_strsave(s); | |
4687 if (s == NULL) | |
4688 ret = FAIL; | |
4689 else | |
4690 { | |
4691 funcexe_T funcexe; | |
4692 | |
4693 // Invoke the function. | |
4694 vim_memset(&funcexe, 0, sizeof(funcexe)); | |
4695 funcexe.firstline = curwin->w_cursor.lnum; | |
4696 funcexe.lastline = curwin->w_cursor.lnum; | |
4697 funcexe.doesrange = &len; | |
4698 funcexe.evaluate = evaluate; | |
4699 funcexe.partial = partial; | |
4700 ret = get_func_tv(s, len, rettv, arg, &funcexe); | |
4701 } | |
4702 vim_free(s); | |
4703 | |
4704 /* If evaluate is FALSE rettv->v_type was not set in | |
4705 * get_func_tv, but it's needed in handle_subscript() to parse | |
4706 * what follows. So set it here. */ | |
4707 if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') | |
4708 { | |
4709 rettv->vval.v_string = NULL; | |
4710 rettv->v_type = VAR_FUNC; | |
4711 } | |
4712 | |
4713 /* Stop the expression evaluation when immediately | |
4714 * aborting on error, or when an interrupt occurred or | |
4715 * an exception was thrown but not caught. */ | |
4716 if (evaluate && aborting()) | |
4717 { | |
4718 if (ret == OK) | |
4719 clear_tv(rettv); | |
4720 ret = FAIL; | |
4721 } | |
4722 } | |
4723 else if (evaluate) | 4743 else if (evaluate) |
4724 ret = get_var_tv(s, len, rettv, NULL, TRUE, FALSE); | 4744 ret = get_var_tv(s, len, rettv, NULL, TRUE, FALSE); |
4725 else | 4745 else |
4726 { | 4746 { |
4727 check_vars(s, len); | 4747 check_vars(s, len); |
4813 int evaluate, | 4833 int evaluate, |
4814 int verbose) /* give error messages */ | 4834 int verbose) /* give error messages */ |
4815 { | 4835 { |
4816 char_u *name; | 4836 char_u *name; |
4817 long len; | 4837 long len; |
4818 funcexe_T funcexe; | 4838 char_u *alias; |
4819 int ret = OK; | |
4820 typval_T base = *rettv; | 4839 typval_T base = *rettv; |
4840 int ret; | |
4821 | 4841 |
4822 // Skip over the ->. | 4842 // Skip over the ->. |
4823 *arg += 2; | 4843 *arg += 2; |
4824 | 4844 rettv->v_type = VAR_UNKNOWN; |
4825 // Locate the method name. | 4845 |
4826 name = *arg; | 4846 name = *arg; |
4827 for (len = 0; eval_isnamec(name[len]); ++len) | 4847 len = get_name_len(arg, &alias, evaluate, TRUE); |
4828 ; | 4848 if (alias != NULL) |
4829 if (len == 0) | 4849 name = alias; |
4850 | |
4851 if (len <= 0) | |
4830 { | 4852 { |
4831 if (verbose) | 4853 if (verbose) |
4832 emsg(_("E260: Missing name after ->")); | 4854 emsg(_("E260: Missing name after ->")); |
4833 return FAIL; | 4855 ret = FAIL; |
4834 } | 4856 } |
4835 | 4857 else |
4836 // Check for the "(". Skip over white space after it. | 4858 { |
4837 if (name[len] != '(') | 4859 if (**arg != '(') |
4838 { | 4860 { |
4839 if (verbose) | 4861 if (verbose) |
4840 semsg(_(e_missingparen), name); | 4862 semsg(_(e_missingparen), name); |
4841 return FAIL; | 4863 ret = FAIL; |
4842 } | 4864 } |
4843 *arg += len; | 4865 else |
4844 | 4866 ret = eval_func(arg, name, len, rettv, evaluate, &base); |
4845 // TODO: if "name" is a function reference, resolve it. | 4867 } |
4846 | |
4847 vim_memset(&funcexe, 0, sizeof(funcexe)); | |
4848 funcexe.evaluate = evaluate; | |
4849 funcexe.basetv = &base; | |
4850 rettv->v_type = VAR_UNKNOWN; | |
4851 ret = get_func_tv(name, len, rettv, arg, &funcexe); | |
4852 | 4868 |
4853 /* Clear the funcref afterwards, so that deleting it while | 4869 /* Clear the funcref afterwards, so that deleting it while |
4854 * evaluating the arguments is possible (see test55). */ | 4870 * evaluating the arguments is possible (see test55). */ |
4855 if (evaluate) | 4871 if (evaluate) |
4856 clear_tv(&base); | 4872 clear_tv(&base); |
4857 | 4873 |
4858 /* Stop the expression evaluation when immediately aborting on | |
4859 * error, or when an interrupt occurred or an exception was thrown | |
4860 * but not caught. */ | |
4861 if (aborting()) | |
4862 { | |
4863 if (ret == OK) | |
4864 clear_tv(rettv); | |
4865 ret = FAIL; | |
4866 } | |
4867 return ret; | 4874 return ret; |
4868 } | 4875 } |
4869 | 4876 |
4870 /* | 4877 /* |
4871 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key". | 4878 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key". |