diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-08-01 08:42:58 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2024-08-01 09:28:19 +0800 |
commit | 8f47a95addf7387b660ae3b76b303a0f946e4f80 (patch) | |
tree | 3a6141e19b58c17035cb6b81e166140e318b4335 /src/nvim/eval.c | |
parent | e820474cde09273608be5f57e1032aab21e3c97d (diff) | |
download | rneovim-8f47a95addf7387b660ae3b76b303a0f946e4f80.tar.gz rneovim-8f47a95addf7387b660ae3b76b303a0f946e4f80.tar.bz2 rneovim-8f47a95addf7387b660ae3b76b303a0f946e4f80.zip |
vim-patch:partial:9.1.0450: evalc. code too complex
Problem: eval.c code too complex
Solution: refactor eval6() and eval9() functions into several smaller
functions (Yegappan Lakshmanan)
closes: vim/vim#14875
https://github.com/vim/vim/commit/51c45e89b50a4841147b9fbd7c6095ab79a10c71
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 189 |
1 files changed, 112 insertions, 77 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index be643b7990..fa519ad701 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1443,7 +1443,7 @@ Object eval_foldtext(win_T *wp) /// The Dict is returned in 'lp'. Returns GLV_OK on success and GLV_FAIL on /// failure. Returns GLV_STOP to stop processing the characters following /// 'key_end'. -static glv_status_T get_lval_dict_item(char *name, lval_T *lp, char *key, int len, char **key_end, +static glv_status_T get_lval_dict_item(lval_T *lp, char *name, char *key, int len, char **key_end, typval_T *var1, int flags, bool unlet, typval_T *rettv) { bool quiet = flags & GLV_QUIET; @@ -1738,7 +1738,7 @@ static char *get_lval_subscript(lval_T *lp, char *p, char *name, typval_T *rettv } if (lp->ll_tv->v_type == VAR_DICT) { - glv_status_T glv_status = get_lval_dict_item(name, lp, key, len, &p, &var1, + glv_status_T glv_status = get_lval_dict_item(lp, name, key, len, &p, &var1, flags, unlet, rettv); if (glv_status == GLV_FAIL) { goto done; @@ -2950,6 +2950,93 @@ static int eval_addlist(typval_T *tv1, typval_T *tv2) return OK; } +/// Concatenate strings "tv1" and "tv2" and store the result in "tv1". +static int eval_concat_str(typval_T *tv1, typval_T *tv2) +{ + char buf1[NUMBUFLEN]; + char buf2[NUMBUFLEN]; + // s1 already checked + const char *const s1 = tv_get_string_buf(tv1, buf1); + const char *const s2 = tv_get_string_buf_chk(tv2, buf2); + if (s2 == NULL) { // Type error? + tv_clear(tv1); + tv_clear(tv2); + return FAIL; + } + + char *p = concat_str(s1, s2); + tv_clear(tv1); + tv1->v_type = VAR_STRING; + tv1->vval.v_string = p; + + return OK; +} + +/// Add or subtract numbers "tv1" and "tv2" and store the result in "tv1". +/// The numbers can be whole numbers or floats. +static int eval_addsub_num(typval_T *tv1, typval_T *tv2, int op) +{ + bool error = false; + varnumber_T n1, n2; + float_T f1 = 0; + float_T f2 = 0; + + if (tv1->v_type == VAR_FLOAT) { + f1 = tv1->vval.v_float; + n1 = 0; + } else { + n1 = tv_get_number_chk(tv1, &error); + if (error) { + // This can only happen for "list + non-list" or + // "blob + non-blob". For "non-list + ..." or + // "something - ...", we returned before evaluating the + // 2nd operand. + tv_clear(tv1); + tv_clear(tv2); + return FAIL; + } + if (tv2->v_type == VAR_FLOAT) { + f1 = (float_T)n1; + } + } + if (tv2->v_type == VAR_FLOAT) { + f2 = tv2->vval.v_float; + n2 = 0; + } else { + n2 = tv_get_number_chk(tv2, &error); + if (error) { + tv_clear(tv1); + tv_clear(tv2); + return FAIL; + } + if (tv1->v_type == VAR_FLOAT) { + f2 = (float_T)n2; + } + } + tv_clear(tv1); + + // If there is a float on either side the result is a float. + if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT) { + if (op == '+') { + f1 = f1 + f2; + } else { + f1 = f1 - f2; + } + tv1->v_type = VAR_FLOAT; + tv1->vval.v_float = f1; + } else { + if (op == '+') { + n1 = n1 + n2; + } else { + n1 = n1 - n2; + } + tv1->v_type = VAR_NUMBER; + tv1->vval.v_number = n1; + } + + return OK; +} + /// Handle fourth level expression: /// + number addition, concatenation of list or blob /// - number subtraction @@ -3005,20 +3092,9 @@ static int eval5(char **arg, typval_T *rettv, evalarg_T *const evalarg) if (evaluate) { // Compute the result. if (op == '.') { - char buf1[NUMBUFLEN]; - char buf2[NUMBUFLEN]; - // s1 already checked - const char *const s1 = tv_get_string_buf(rettv, buf1); - const char *const s2 = tv_get_string_buf_chk(&var2, buf2); - if (s2 == NULL) { // Type error? - tv_clear(rettv); - tv_clear(&var2); + if (eval_concat_str(rettv, &var2) == FAIL) { return FAIL; } - char *p = concat_str(s1, s2); - tv_clear(rettv); - rettv->v_type = VAR_STRING; - rettv->vval.v_string = p; } else if (op == '+' && rettv->v_type == VAR_BLOB && var2.v_type == VAR_BLOB) { eval_addblob(rettv, &var2); } else if (op == '+' && rettv->v_type == VAR_LIST && var2.v_type == VAR_LIST) { @@ -3026,62 +3102,8 @@ static int eval5(char **arg, typval_T *rettv, evalarg_T *const evalarg) return FAIL; } } else { - bool error = false; - varnumber_T n1, n2; - float_T f1 = 0; - float_T f2 = 0; - - if (rettv->v_type == VAR_FLOAT) { - f1 = rettv->vval.v_float; - n1 = 0; - } else { - n1 = tv_get_number_chk(rettv, &error); - if (error) { - // This can only happen for "list + non-list" or - // "blob + non-blob". For "non-list + ..." or - // "something - ...", we returned before evaluating the - // 2nd operand. - tv_clear(rettv); - tv_clear(&var2); - return FAIL; - } - if (var2.v_type == VAR_FLOAT) { - f1 = (float_T)n1; - } - } - if (var2.v_type == VAR_FLOAT) { - f2 = var2.vval.v_float; - n2 = 0; - } else { - n2 = tv_get_number_chk(&var2, &error); - if (error) { - tv_clear(rettv); - tv_clear(&var2); - return FAIL; - } - if (rettv->v_type == VAR_FLOAT) { - f2 = (float_T)n2; - } - } - tv_clear(rettv); - - // If there is a float on either side the result is a float. - if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT) { - if (op == '+') { - f1 = f1 + f2; - } else { - f1 = f1 - f2; - } - rettv->v_type = VAR_FLOAT; - rettv->vval.v_float = f1; - } else { - if (op == '+') { - n1 = n1 + n2; - } else { - n1 = n1 - n2; - } - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = n1; + if (eval_addsub_num(rettv, &var2, op) == FAIL) { + return FAIL; } } tv_clear(&var2); @@ -3301,14 +3323,9 @@ static int eval7(char **arg, typval_T *rettv, evalarg_T *const evalarg, bool wan ret = eval_list(arg, rettv, evalarg); break; - // Dictionary: #{key: val, key: val} + // Literal Dictionary: #{key: val, key: val} case '#': - if ((*arg)[1] == '{') { - (*arg)++; - ret = eval_dict(arg, rettv, evalarg, true); - } else { - ret = NOTDONE; - } + ret = eval_lit_dict(arg, rettv, evalarg); break; // Lambda: {arg, arg -> expr} @@ -5274,6 +5291,24 @@ failret: return OK; } +/// Evaluate a literal dictionary: #{key: val, key: val} +/// "*arg" points to the "#". +/// On return, "*arg" points to the character after the Dict. +/// Return OK or FAIL. Returns NOTDONE for {expr}. +static int eval_lit_dict(char **arg, typval_T *rettv, evalarg_T *const evalarg) +{ + int ret = OK; + + if ((*arg)[1] == '{') { + (*arg)++; + ret = eval_dict(arg, rettv, evalarg, true); + } else { + ret = NOTDONE; + } + + return ret; +} + /// Convert the string to a floating point number /// /// This uses strtod(). setlocale(LC_NUMERIC, "C") has been used earlier to |