diff options
author | ZyX <kp-pav@yandex.ru> | 2016-07-26 23:16:23 +0300 |
---|---|---|
committer | ZyX <kp-pav@yandex.ru> | 2017-03-29 10:05:06 +0300 |
commit | fb146e80aa1ead96518f38b9684e39249bc83485 (patch) | |
tree | 8a157d55108b19ae40cc85817b2620bdcf809905 /src/nvim/eval/executor.c | |
parent | 18e7d552008b92dd3ecd42bf6855530838fd22ab (diff) | |
download | rneovim-fb146e80aa1ead96518f38b9684e39249bc83485.tar.gz rneovim-fb146e80aa1ead96518f38b9684e39249bc83485.tar.bz2 rneovim-fb146e80aa1ead96518f38b9684e39249bc83485.zip |
eval: Split eval.c into smaller files
Diffstat (limited to 'src/nvim/eval/executor.c')
-rw-r--r-- | src/nvim/eval/executor.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c new file mode 100644 index 0000000000..ab48ace400 --- /dev/null +++ b/src/nvim/eval/executor.c @@ -0,0 +1,114 @@ +#include "nvim/eval/typval.h" +#include "nvim/eval/executor.h" +#include "nvim/eval.h" +#include "nvim/message.h" +#include "nvim/vim.h" +#include "nvim/globals.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/executor.c.generated.h" +#endif + +static char *e_letwrong = N_("E734: Wrong variable type for %s="); + +char *e_listidx = N_("E684: list index out of range: %" PRId64); + +/// Hanle tv1 += tv2, -=, .= +/// +/// @param[in,out] tv1 First operand, modified typval. +/// @param[in] tv2 Second operand. +/// @param[in] op Used operator. +/// +/// @return OK or FAIL. +int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, + const char *const op) + FUNC_ATTR_NONNULL_ALL +{ + // Can't do anything with a Funcref, a Dict or special value on the right. + if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT) { + switch (tv1->v_type) { + case VAR_DICT: + case VAR_FUNC: + case VAR_PARTIAL: + case VAR_SPECIAL: { + break; + } + case VAR_LIST: { + if (*op != '+' || tv2->v_type != VAR_LIST) { + break; + } + // List += List + if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL) { + tv_list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL); + } + return OK; + } + case VAR_NUMBER: + case VAR_STRING: { + if (tv2->v_type == VAR_LIST) { + break; + } + if (*op == '+' || *op == '-') { + // nr += nr or nr -= nr + varnumber_T n = get_tv_number(tv1); + if (tv2->v_type == VAR_FLOAT) { + float_T f = n; + + if (*op == '+') { + f += tv2->vval.v_float; + } else { + f -= tv2->vval.v_float; + } + tv_clear(tv1); + tv1->v_type = VAR_FLOAT; + tv1->vval.v_float = f; + } else { + if (*op == '+') { + n += get_tv_number(tv2); + } else { + n -= get_tv_number(tv2); + } + tv_clear(tv1); + tv1->v_type = VAR_NUMBER; + tv1->vval.v_number = n; + } + } else { + // str .= str + if (tv2->v_type == VAR_FLOAT) { + break; + } + char *s = (char *)get_tv_string(tv1); + char numbuf[NUMBUFLEN]; + s = (char *)concat_str((char_u *)s, + get_tv_string_buf(tv2, (char_u *)numbuf)); + tv_clear(tv1); + tv1->v_type = VAR_STRING; + tv1->vval.v_string = (char_u *)s; + } + return OK; + } + case VAR_FLOAT: { + if (*op == '.' || (tv2->v_type != VAR_FLOAT + && tv2->v_type != VAR_NUMBER + && tv2->v_type != VAR_STRING)) { + break; + } + const float_T f = (tv2->v_type == VAR_FLOAT + ? tv2->vval.v_float + : get_tv_number(tv2)); + if (*op == '+') { + tv1->vval.v_float += f; + } else { + tv1->vval.v_float -= f; + } + return OK; + } + case VAR_UNKNOWN: { + assert(false); + } + } + } + + EMSG2(_(e_letwrong), op); + return FAIL; +} |