aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval/executor.c
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2016-07-26 23:16:23 +0300
committerZyX <kp-pav@yandex.ru>2017-03-29 10:05:06 +0300
commitfb146e80aa1ead96518f38b9684e39249bc83485 (patch)
tree8a157d55108b19ae40cc85817b2620bdcf809905 /src/nvim/eval/executor.c
parent18e7d552008b92dd3ecd42bf6855530838fd22ab (diff)
downloadrneovim-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.c114
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;
+}