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".