Mercurial > vim
comparison src/eval.c @ 17763:117c7795a979 v8.1.1878
patch 8.1.1878: negative float before method not parsed correctly
commit https://github.com/vim/vim/commit/9cfe8f6e68de4bfb5942d84f4465de914a747b3f
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Aug 17 21:04:16 2019 +0200
patch 8.1.1878: negative float before method not parsed correctly
Problem: Negative float before method not parsed correctly.
Solution: Apply "!" and "-" in front of expression before using ->.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 17 Aug 2019 21:15:03 +0200 |
parents | 06c3e15ad84d |
children | 04245f071792 |
comparison
equal
deleted
inserted
replaced
17762:87d3311b3401 | 17763:117c7795a979 |
---|---|
239 static int eval3(char_u **arg, typval_T *rettv, int evaluate); | 239 static int eval3(char_u **arg, typval_T *rettv, int evaluate); |
240 static int eval4(char_u **arg, typval_T *rettv, int evaluate); | 240 static int eval4(char_u **arg, typval_T *rettv, int evaluate); |
241 static int eval5(char_u **arg, typval_T *rettv, int evaluate); | 241 static int eval5(char_u **arg, typval_T *rettv, int evaluate); |
242 static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string); | 242 static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string); |
243 static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string); | 243 static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string); |
244 static int eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp); | |
244 | 245 |
245 static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate); | 246 static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate); |
246 static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate); | 247 static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate); |
247 static int free_unref_items(int copyID); | 248 static int free_unref_items(int copyID); |
248 static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate); | 249 static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate); |
1808 error = TRUE; | 1809 error = TRUE; |
1809 else | 1810 else |
1810 { | 1811 { |
1811 /* handle d.key, l[idx], f(expr) */ | 1812 /* handle d.key, l[idx], f(expr) */ |
1812 arg_subsc = arg; | 1813 arg_subsc = arg; |
1813 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL) | 1814 if (handle_subscript(&arg, &tv, TRUE, TRUE, |
1815 name, &name) == FAIL) | |
1814 error = TRUE; | 1816 error = TRUE; |
1815 else | 1817 else |
1816 { | 1818 { |
1817 if (arg == arg_subsc && len == 2 && name[1] == ':') | 1819 if (arg == arg_subsc && len == 2 && name[1] == ':') |
1818 { | 1820 { |
4754 *arg = skipwhite(*arg); | 4756 *arg = skipwhite(*arg); |
4755 | 4757 |
4756 /* Handle following '[', '(' and '.' for expr[expr], expr.name, | 4758 /* Handle following '[', '(' and '.' for expr[expr], expr.name, |
4757 * expr(expr), expr->name(expr) */ | 4759 * expr(expr), expr->name(expr) */ |
4758 if (ret == OK) | 4760 if (ret == OK) |
4759 ret = handle_subscript(arg, rettv, evaluate, TRUE); | 4761 ret = handle_subscript(arg, rettv, evaluate, TRUE, |
4762 start_leader, &end_leader); | |
4760 | 4763 |
4761 /* | 4764 /* |
4762 * Apply logical NOT and unary '-', from right to left, ignore '+'. | 4765 * Apply logical NOT and unary '-', from right to left, ignore '+'. |
4763 */ | 4766 */ |
4764 if (ret == OK && evaluate && end_leader > start_leader) | 4767 if (ret == OK && evaluate && end_leader > start_leader) |
4765 { | 4768 ret = eval7_leader(rettv, start_leader, &end_leader); |
4766 int error = FALSE; | 4769 return ret; |
4767 varnumber_T val = 0; | 4770 } |
4771 | |
4772 /* | |
4773 * Apply the leading "!" and "-" before an eval7 expression to "rettv". | |
4774 * Adjusts "end_leaderp" until it is at "start_leader". | |
4775 */ | |
4776 static int | |
4777 eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp) | |
4778 { | |
4779 char_u *end_leader = *end_leaderp; | |
4780 int ret = OK; | |
4781 int error = FALSE; | |
4782 varnumber_T val = 0; | |
4768 #ifdef FEAT_FLOAT | 4783 #ifdef FEAT_FLOAT |
4769 float_T f = 0.0; | 4784 float_T f = 0.0; |
4770 | 4785 |
4786 if (rettv->v_type == VAR_FLOAT) | |
4787 f = rettv->vval.v_float; | |
4788 else | |
4789 #endif | |
4790 val = tv_get_number_chk(rettv, &error); | |
4791 if (error) | |
4792 { | |
4793 clear_tv(rettv); | |
4794 ret = FAIL; | |
4795 } | |
4796 else | |
4797 { | |
4798 while (end_leader > start_leader) | |
4799 { | |
4800 --end_leader; | |
4801 if (*end_leader == '!') | |
4802 { | |
4803 #ifdef FEAT_FLOAT | |
4804 if (rettv->v_type == VAR_FLOAT) | |
4805 f = !f; | |
4806 else | |
4807 #endif | |
4808 val = !val; | |
4809 } | |
4810 else if (*end_leader == '-') | |
4811 { | |
4812 #ifdef FEAT_FLOAT | |
4813 if (rettv->v_type == VAR_FLOAT) | |
4814 f = -f; | |
4815 else | |
4816 #endif | |
4817 val = -val; | |
4818 } | |
4819 } | |
4820 #ifdef FEAT_FLOAT | |
4771 if (rettv->v_type == VAR_FLOAT) | 4821 if (rettv->v_type == VAR_FLOAT) |
4772 f = rettv->vval.v_float; | 4822 { |
4823 clear_tv(rettv); | |
4824 rettv->vval.v_float = f; | |
4825 } | |
4773 else | 4826 else |
4774 #endif | 4827 #endif |
4775 val = tv_get_number_chk(rettv, &error); | |
4776 if (error) | |
4777 { | 4828 { |
4778 clear_tv(rettv); | 4829 clear_tv(rettv); |
4779 ret = FAIL; | 4830 rettv->v_type = VAR_NUMBER; |
4780 } | 4831 rettv->vval.v_number = val; |
4781 else | 4832 } |
4782 { | 4833 } |
4783 while (end_leader > start_leader) | 4834 *end_leaderp = end_leader; |
4784 { | |
4785 --end_leader; | |
4786 if (*end_leader == '!') | |
4787 { | |
4788 #ifdef FEAT_FLOAT | |
4789 if (rettv->v_type == VAR_FLOAT) | |
4790 f = !f; | |
4791 else | |
4792 #endif | |
4793 val = !val; | |
4794 } | |
4795 else if (*end_leader == '-') | |
4796 { | |
4797 #ifdef FEAT_FLOAT | |
4798 if (rettv->v_type == VAR_FLOAT) | |
4799 f = -f; | |
4800 else | |
4801 #endif | |
4802 val = -val; | |
4803 } | |
4804 } | |
4805 #ifdef FEAT_FLOAT | |
4806 if (rettv->v_type == VAR_FLOAT) | |
4807 { | |
4808 clear_tv(rettv); | |
4809 rettv->vval.v_float = f; | |
4810 } | |
4811 else | |
4812 #endif | |
4813 { | |
4814 clear_tv(rettv); | |
4815 rettv->v_type = VAR_NUMBER; | |
4816 rettv->vval.v_number = val; | |
4817 } | |
4818 } | |
4819 } | |
4820 | |
4821 return ret; | 4835 return ret; |
4822 } | 4836 } |
4823 | 4837 |
4824 /* | 4838 /* |
4825 * Call the function referred to in "rettv". | 4839 * Call the function referred to in "rettv". |
7537 */ | 7551 */ |
7538 int | 7552 int |
7539 handle_subscript( | 7553 handle_subscript( |
7540 char_u **arg, | 7554 char_u **arg, |
7541 typval_T *rettv, | 7555 typval_T *rettv, |
7542 int evaluate, /* do more than finding the end */ | 7556 int evaluate, // do more than finding the end |
7543 int verbose) /* give error messages */ | 7557 int verbose, // give error messages |
7558 char_u *start_leader, // start of '!' and '-' prefixes | |
7559 char_u **end_leaderp) // end of '!' and '-' prefixes | |
7544 { | 7560 { |
7545 int ret = OK; | 7561 int ret = OK; |
7546 dict_T *selfdict = NULL; | 7562 dict_T *selfdict = NULL; |
7547 | 7563 |
7548 // "." is ".name" lookup when we found a dict or when evaluating and | 7564 // "." is ".name" lookup when we found a dict or when evaluating and |
7574 dict_unref(selfdict); | 7590 dict_unref(selfdict); |
7575 selfdict = NULL; | 7591 selfdict = NULL; |
7576 } | 7592 } |
7577 else if (**arg == '-') | 7593 else if (**arg == '-') |
7578 { | 7594 { |
7579 if ((*arg)[2] == '{') | 7595 // Expression "-1.0->method()" applies the leader "-" before |
7580 // expr->{lambda}() | 7596 // applying ->. |
7581 ret = eval_lambda(arg, rettv, evaluate, verbose); | 7597 if (evaluate && *end_leaderp > start_leader) |
7582 else | 7598 ret = eval7_leader(rettv, start_leader, end_leaderp); |
7583 // expr->name() | 7599 if (ret == OK) |
7584 ret = eval_method(arg, rettv, evaluate, verbose); | 7600 { |
7601 if ((*arg)[2] == '{') | |
7602 // expr->{lambda}() | |
7603 ret = eval_lambda(arg, rettv, evaluate, verbose); | |
7604 else | |
7605 // expr->name() | |
7606 ret = eval_method(arg, rettv, evaluate, verbose); | |
7607 } | |
7585 } | 7608 } |
7586 else /* **arg == '[' || **arg == '.' */ | 7609 else /* **arg == '[' || **arg == '.' */ |
7587 { | 7610 { |
7588 dict_unref(selfdict); | 7611 dict_unref(selfdict); |
7589 if (rettv->v_type == VAR_DICT) | 7612 if (rettv->v_type == VAR_DICT) |
9801 name = tofree; | 9824 name = tofree; |
9802 n = (get_var_tv(name, len, &tv, NULL, FALSE, TRUE) == OK); | 9825 n = (get_var_tv(name, len, &tv, NULL, FALSE, TRUE) == OK); |
9803 if (n) | 9826 if (n) |
9804 { | 9827 { |
9805 /* handle d.key, l[idx], f(expr) */ | 9828 /* handle d.key, l[idx], f(expr) */ |
9806 n = (handle_subscript(&var, &tv, TRUE, FALSE) == OK); | 9829 n = (handle_subscript(&var, &tv, TRUE, FALSE, name, &name) == OK); |
9807 if (n) | 9830 if (n) |
9808 clear_tv(&tv); | 9831 clear_tv(&tv); |
9809 } | 9832 } |
9810 } | 9833 } |
9811 if (*var != NUL) | 9834 if (*var != NUL) |