mirror of
https://github.com/neovim/neovim.git
synced 2025-10-04 08:56:29 +00:00
eval: Split eval.c into smaller files
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <msgpack.h>
|
||||
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/encode.h"
|
||||
#include "nvim/ascii.h"
|
||||
@@ -118,18 +118,18 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
||||
if (last_container.container.vval.v_list->lv_len != 0
|
||||
&& !obj.didcomma) {
|
||||
EMSG2(_("E474: Expected comma before list item: %s"), val_location);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
}
|
||||
assert(last_container.special_val == NULL);
|
||||
listitem_T *obj_li = listitem_alloc();
|
||||
listitem_T *obj_li = tv_list_item_alloc();
|
||||
obj_li->li_tv = obj.val;
|
||||
list_append(last_container.container.vval.v_list, obj_li);
|
||||
tv_list_append(last_container.container.vval.v_list, obj_li);
|
||||
} else if (last_container.stack_index == kv_size(*stack) - 2) {
|
||||
if (!obj.didcolon) {
|
||||
EMSG2(_("E474: Expected colon before dictionary value: %s"),
|
||||
val_location);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
}
|
||||
ValuesStackItem key = kv_pop(*stack);
|
||||
@@ -139,33 +139,33 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
||||
|| key.val.vval.v_string == NULL
|
||||
|| *key.val.vval.v_string == NUL));
|
||||
dictitem_T *obj_di = dictitem_alloc(key.val.vval.v_string);
|
||||
clear_tv(&key.val);
|
||||
tv_clear(&key.val);
|
||||
if (dict_add(last_container.container.vval.v_dict, obj_di)
|
||||
== FAIL) {
|
||||
assert(false);
|
||||
}
|
||||
obj_di->di_tv = obj.val;
|
||||
} else {
|
||||
list_T *const kv_pair = list_alloc();
|
||||
list_append_list(last_container.special_val, kv_pair);
|
||||
listitem_T *const key_li = listitem_alloc();
|
||||
list_T *const kv_pair = tv_list_alloc();
|
||||
tv_list_append_list(last_container.special_val, kv_pair);
|
||||
listitem_T *const key_li = tv_list_item_alloc();
|
||||
key_li->li_tv = key.val;
|
||||
list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = listitem_alloc();
|
||||
tv_list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = tv_list_item_alloc();
|
||||
val_li->li_tv = obj.val;
|
||||
list_append(kv_pair, val_li);
|
||||
tv_list_append(kv_pair, val_li);
|
||||
}
|
||||
} else {
|
||||
// Object with key only
|
||||
if (!obj.is_special_string && obj.val.v_type != VAR_STRING) {
|
||||
EMSG2(_("E474: Expected string key: %s"), *pp);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
} else if (!obj.didcomma
|
||||
&& (last_container.special_val == NULL
|
||||
&& (DICT_LEN(last_container.container.vval.v_dict) != 0))) {
|
||||
EMSG2(_("E474: Expected comma before dictionary key: %s"), val_location);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
}
|
||||
// Handle empty key and key represented as special dictionary
|
||||
@@ -175,14 +175,14 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
||||
|| *obj.val.vval.v_string == NUL
|
||||
|| dict_find(last_container.container.vval.v_dict,
|
||||
obj.val.vval.v_string, -1))) {
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
|
||||
// Restart
|
||||
(void) kv_pop(*container_stack);
|
||||
ValuesStackItem last_container_val =
|
||||
kv_A(*stack, last_container.stack_index);
|
||||
while (kv_size(*stack) > last_container.stack_index) {
|
||||
clear_tv(&(kv_pop(*stack).val));
|
||||
tv_clear(&(kv_pop(*stack).val));
|
||||
}
|
||||
*pp = last_container.s;
|
||||
*didcomma = last_container_val.didcomma;
|
||||
@@ -430,7 +430,7 @@ static inline int parse_json_string(vimconv_T *const conv,
|
||||
}
|
||||
if (hasnul) {
|
||||
typval_T obj;
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(&obj, kMPString, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -439,7 +439,7 @@ static inline int parse_json_string(vimconv_T *const conv,
|
||||
}));
|
||||
if (encode_list_write((void *) list, str, (size_t) (str_end - str))
|
||||
== -1) {
|
||||
clear_tv(&obj);
|
||||
tv_clear(&obj);
|
||||
goto parse_json_string_fail;
|
||||
}
|
||||
xfree(str);
|
||||
@@ -806,7 +806,7 @@ json_decode_string_cycle_start:
|
||||
break;
|
||||
}
|
||||
case '[': {
|
||||
list_T *list = list_alloc();
|
||||
list_T *list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
typval_T tv = {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -827,7 +827,7 @@ json_decode_string_cycle_start:
|
||||
list_T *val_list = NULL;
|
||||
if (next_map_special) {
|
||||
next_map_special = false;
|
||||
val_list = list_alloc();
|
||||
val_list = tv_list_alloc();
|
||||
val_list->lv_refcount++;
|
||||
create_special_dict(&tv, kMPMap, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -887,7 +887,7 @@ json_decode_string_after_cycle:
|
||||
json_decode_string_fail:
|
||||
ret = FAIL;
|
||||
while (kv_size(stack)) {
|
||||
clear_tv(&(kv_pop(stack).val));
|
||||
tv_clear(&(kv_pop(stack).val));
|
||||
}
|
||||
json_decode_string_ret:
|
||||
kv_destroy(stack);
|
||||
@@ -933,7 +933,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
.vval = { .v_number = (varnumber_T) mobj.via.u64 },
|
||||
};
|
||||
} else {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -941,10 +941,10 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
.vval = { .v_list = list },
|
||||
}));
|
||||
uint64_t n = mobj.via.u64;
|
||||
list_append_number(list, 1);
|
||||
list_append_number(list, (varnumber_T) ((n >> 62) & 0x3));
|
||||
list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF));
|
||||
list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF));
|
||||
tv_list_append_number(list, 1);
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
|
||||
tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -956,18 +956,18 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
.vval = { .v_number = (varnumber_T) mobj.via.i64 },
|
||||
};
|
||||
} else {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
.v_lock = VAR_UNLOCKED,
|
||||
.vval = { .v_list = list },
|
||||
}));
|
||||
uint64_t n = -((uint64_t) mobj.via.i64);
|
||||
list_append_number(list, -1);
|
||||
list_append_number(list, (varnumber_T) ((n >> 62) & 0x3));
|
||||
list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF));
|
||||
list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF));
|
||||
uint64_t n = -((uint64_t)mobj.via.i64);
|
||||
tv_list_append_number(list, -1);
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
|
||||
tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -980,7 +980,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
break;
|
||||
}
|
||||
case MSGPACK_OBJECT_STR: {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPString, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -1002,7 +1002,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
};
|
||||
break;
|
||||
}
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPBinary, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -1016,7 +1016,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
break;
|
||||
}
|
||||
case MSGPACK_OBJECT_ARRAY: {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
*rettv = (typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -1024,9 +1024,9 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
.vval = { .v_list = list },
|
||||
};
|
||||
for (size_t i = 0; i < mobj.via.array.size; i++) {
|
||||
listitem_T *const li = listitem_alloc();
|
||||
listitem_T *const li = tv_list_item_alloc();
|
||||
li->li_tv.v_type = VAR_UNKNOWN;
|
||||
list_append(list, li);
|
||||
tv_list_append(list, li);
|
||||
if (msgpack_to_vim(mobj.via.array.ptr[i], &li->li_tv) == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
@@ -1057,7 +1057,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
di->di_tv.v_type = VAR_UNKNOWN;
|
||||
if (dict_add(dict, di) == FAIL) {
|
||||
// Duplicate key: fallback to generic map
|
||||
clear_tv(rettv);
|
||||
tv_clear(rettv);
|
||||
xfree(di);
|
||||
goto msgpack_to_vim_generic_map;
|
||||
}
|
||||
@@ -1067,7 +1067,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
||||
}
|
||||
break;
|
||||
msgpack_to_vim_generic_map: {}
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPMap, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
@@ -1075,14 +1075,14 @@ msgpack_to_vim_generic_map: {}
|
||||
.vval = { .v_list = list },
|
||||
}));
|
||||
for (size_t i = 0; i < mobj.via.map.size; i++) {
|
||||
list_T *const kv_pair = list_alloc();
|
||||
list_append_list(list, kv_pair);
|
||||
listitem_T *const key_li = listitem_alloc();
|
||||
list_T *const kv_pair = tv_list_alloc();
|
||||
tv_list_append_list(list, kv_pair);
|
||||
listitem_T *const key_li = tv_list_item_alloc();
|
||||
key_li->li_tv.v_type = VAR_UNKNOWN;
|
||||
list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = listitem_alloc();
|
||||
tv_list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = tv_list_item_alloc();
|
||||
val_li->li_tv.v_type = VAR_UNKNOWN;
|
||||
list_append(kv_pair, val_li);
|
||||
tv_list_append(kv_pair, val_li);
|
||||
if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_li->li_tv) == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
@@ -1093,11 +1093,11 @@ msgpack_to_vim_generic_map: {}
|
||||
break;
|
||||
}
|
||||
case MSGPACK_OBJECT_EXT: {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
list_append_number(list, mobj.via.ext.type);
|
||||
list_T *const ext_val_list = list_alloc();
|
||||
list_append_list(list, ext_val_list);
|
||||
tv_list_append_number(list, mobj.via.ext.type);
|
||||
list_T *const ext_val_list = tv_list_alloc();
|
||||
tv_list_append_list(list, ext_val_list);
|
||||
create_special_dict(rettv, kMPExt, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
.v_lock = VAR_UNLOCKED,
|
||||
|
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <msgpack.h>
|
||||
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/decode.h.generated.h"
|
||||
|
@@ -13,7 +13,7 @@
|
||||
#include "nvim/eval/encode.h"
|
||||
#include "nvim/buffer_defs.h" // vimconv_T
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/garray.h"
|
||||
#include "nvim/mbyte.h"
|
||||
#include "nvim/message.h"
|
||||
@@ -45,7 +45,8 @@ const char *const encode_special_var_names[] = {
|
||||
#endif
|
||||
|
||||
/// Msgpack callback for writing to readfile()-style list
|
||||
int encode_list_write(void *data, const char *buf, size_t len)
|
||||
int encode_list_write(void *const data, const char *const buf, const size_t len)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
@@ -80,11 +81,11 @@ int encode_list_write(void *data, const char *buf, size_t len)
|
||||
str = xmemdupz(line_start, line_length);
|
||||
memchrsub(str, NUL, NL, line_length);
|
||||
}
|
||||
list_append_allocated_string(list, str);
|
||||
tv_list_append_allocated_string(list, str);
|
||||
line_end++;
|
||||
}
|
||||
if (line_end == end) {
|
||||
list_append_allocated_string(list, NULL);
|
||||
tv_list_append_allocated_string(list, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
114
src/nvim/eval/executor.c
Normal file
114
src/nvim/eval/executor.c
Normal file
@@ -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;
|
||||
}
|
9
src/nvim/eval/executor.h
Normal file
9
src/nvim/eval/executor.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef NVIM_EVAL_EXECUTOR_H
|
||||
#define NVIM_EVAL_EXECUTOR_H
|
||||
|
||||
extern char *e_listidx;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/executor.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_EVAL_EXECUTOR_H
|
11
src/nvim/eval/gc.c
Normal file
11
src/nvim/eval/gc.c
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/eval/gc.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/gc.c.generated.h"
|
||||
#endif
|
||||
|
||||
/// Head of list of all dictionaries
|
||||
dict_T *gc_first_dict = NULL;
|
||||
/// Head of list of all lists
|
||||
list_T *gc_first_list = NULL;
|
12
src/nvim/eval/gc.h
Normal file
12
src/nvim/eval/gc.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef NVIM_EVAL_GC_H
|
||||
#define NVIM_EVAL_GC_H
|
||||
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
extern dict_T *gc_first_dict;
|
||||
extern list_T *gc_first_list;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/gc.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_EVAL_GC_H
|
1171
src/nvim/eval/typval.c
Normal file
1171
src/nvim/eval/typval.c
Normal file
File diff suppressed because it is too large
Load Diff
285
src/nvim/eval/typval.h
Normal file
285
src/nvim/eval/typval.h
Normal file
@@ -0,0 +1,285 @@
|
||||
#ifndef NVIM_EVAL_TYPVAL_H
|
||||
#define NVIM_EVAL_TYPVAL_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "nvim/hashtab.h"
|
||||
#include "nvim/garray.h"
|
||||
#include "nvim/mbyte.h"
|
||||
#include "nvim/lib/queue.h"
|
||||
#include "nvim/profile.h" // for proftime_T
|
||||
#include "nvim/pos.h" // for linenr_T
|
||||
|
||||
/// Type used for VimL VAR_NUMBER values
|
||||
typedef int varnumber_T;
|
||||
|
||||
/// Type used for VimL VAR_FLOAT values
|
||||
typedef double float_T;
|
||||
|
||||
/// Maximal possible value of varnumber_T variable
|
||||
#define VARNUMBER_MAX INT_MAX
|
||||
|
||||
/// Mimimal possible value of varnumber_T variable
|
||||
#define VARNUMBER_MIN INT_MIN
|
||||
|
||||
/// %d printf format specifier for varnumber_T
|
||||
#define PRIdVARNUMBER "d"
|
||||
|
||||
typedef struct listvar_S list_T;
|
||||
typedef struct dictvar_S dict_T;
|
||||
typedef struct partial_S partial_T;
|
||||
|
||||
/// Special variable values
|
||||
typedef enum {
|
||||
kSpecialVarFalse, ///< v:false
|
||||
kSpecialVarTrue, ///< v:true
|
||||
kSpecialVarNull, ///< v:null
|
||||
} SpecialVarValue;
|
||||
|
||||
/// Variable lock status for typval_T.v_lock
|
||||
typedef enum {
|
||||
VAR_UNLOCKED = 0, ///< Not locked.
|
||||
VAR_LOCKED = 1, ///< User lock, can be unlocked.
|
||||
VAR_FIXED = 2, ///< Locked forever.
|
||||
} VarLockStatus;
|
||||
|
||||
/// VimL variable types, for use in typval_T.v_type
|
||||
typedef enum {
|
||||
VAR_UNKNOWN = 0, ///< Unknown (unspecified) value.
|
||||
VAR_NUMBER, ///< Number, .v_number is used.
|
||||
VAR_STRING, ///< String, .v_string is used.
|
||||
VAR_FUNC, ///< Function reference, .v_string is used as function name.
|
||||
VAR_LIST, ///< List, .v_list is used.
|
||||
VAR_DICT, ///< Dictionary, .v_dict is used.
|
||||
VAR_FLOAT, ///< Floating-point value, .v_float is used.
|
||||
VAR_SPECIAL, ///< Special value (true, false, null), .v_special
|
||||
///< is used.
|
||||
VAR_PARTIAL, ///< Partial, .v_partial is used.
|
||||
} VarType;
|
||||
|
||||
/// Structure that holds an internal variable value
|
||||
typedef struct {
|
||||
VarType v_type; ///< Variable type.
|
||||
VarLockStatus v_lock; ///< Variable lock status.
|
||||
union typval_vval_union {
|
||||
varnumber_T v_number; ///< Number, for VAR_NUMBER.
|
||||
SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL.
|
||||
float_T v_float; ///< Floating-point number, for VAR_FLOAT.
|
||||
char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
|
||||
list_T *v_list; ///< List for VAR_LIST, can be NULL.
|
||||
dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
|
||||
partial_T *v_partial; ///< Closure: function with args.
|
||||
} vval; ///< Actual value.
|
||||
} typval_T;
|
||||
|
||||
/// Values for (struct dictvar_S).dv_scope
|
||||
typedef enum {
|
||||
VAR_NO_SCOPE = 0, ///< Not a scope dictionary.
|
||||
VAR_SCOPE = 1, ///< Scope dictionary which requires prefix (a:, v:, …).
|
||||
VAR_DEF_SCOPE = 2, ///< Scope dictionary which may be accessed without prefix
|
||||
///< (l:, g:).
|
||||
} ScopeType;
|
||||
|
||||
/// Structure to hold an item of a list
|
||||
typedef struct listitem_S listitem_T;
|
||||
|
||||
struct listitem_S {
|
||||
listitem_T *li_next; ///< Next item in list.
|
||||
listitem_T *li_prev; ///< Previous item in list.
|
||||
typval_T li_tv; ///< Item value.
|
||||
};
|
||||
|
||||
/// Structure used by those that are using an item in a list
|
||||
typedef struct listwatch_S listwatch_T;
|
||||
|
||||
struct listwatch_S {
|
||||
listitem_T *lw_item; ///< Item being watched.
|
||||
listwatch_T *lw_next; ///< Next watcher.
|
||||
};
|
||||
|
||||
/// Structure to hold info about a list
|
||||
struct listvar_S {
|
||||
listitem_T *lv_first; ///< First item, NULL if none.
|
||||
listitem_T *lv_last; ///< Last item, NULL if none.
|
||||
int lv_refcount; ///< Reference count.
|
||||
int lv_len; ///< Number of items.
|
||||
listwatch_T *lv_watch; ///< First watcher, NULL if none.
|
||||
int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx].
|
||||
listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx".
|
||||
int lv_copyID; ///< ID used by deepcopy().
|
||||
list_T *lv_copylist; ///< Copied list used by deepcopy().
|
||||
VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED.
|
||||
list_T *lv_used_next; ///< next list in used lists list.
|
||||
list_T *lv_used_prev; ///< Previous list in used lists list.
|
||||
};
|
||||
|
||||
// Static list with 10 items. Use init_static_list() to initialize.
|
||||
typedef struct {
|
||||
list_T sl_list; // must be first
|
||||
listitem_T sl_items[10];
|
||||
} staticList10_T;
|
||||
|
||||
// Structure to hold an item of a Dictionary.
|
||||
// Also used for a variable.
|
||||
// The key is copied into "di_key" to avoid an extra alloc/free for it.
|
||||
struct dictitem_S {
|
||||
typval_T di_tv; ///< type and value of the variable
|
||||
char_u di_flags; ///< flags (only used for variable)
|
||||
char_u di_key[1]; ///< key (actually longer!)
|
||||
};
|
||||
|
||||
#define TV_DICTITEM_STRUCT(KEY_LEN) \
|
||||
struct { \
|
||||
typval_T di_tv; /* Structure that holds scope dictionary itself. */ \
|
||||
uint8_t di_flags; /* Flags. */ \
|
||||
char_u di_key[KEY_LEN]; /* NUL. */ \
|
||||
}
|
||||
|
||||
/// Structure to hold a scope dictionary
|
||||
///
|
||||
/// @warning Must be compatible with dictitem_T.
|
||||
///
|
||||
/// For use in find_var_in_ht to pretend that it found dictionary item when it
|
||||
/// finds scope dictionary.
|
||||
typedef TV_DICTITEM_STRUCT(1) ScopeDictDictItem;
|
||||
|
||||
/// Structure to hold an item of a Dictionary
|
||||
///
|
||||
/// @warning Must be compatible with ScopeDictDictItem.
|
||||
///
|
||||
/// Also used for a variable.
|
||||
typedef TV_DICTITEM_STRUCT() dictitem_T;
|
||||
|
||||
/// Flags for dictitem_T.di_flags
|
||||
typedef enum {
|
||||
DI_FLAGS_RO = 1, ///< Read-only value
|
||||
DI_FLAGS_RO_SBX = 2, ///< Value, read-only in the sandbox
|
||||
DI_FLAGS_FIX = 4, ///< Fixed value: cannot be :unlet or remove()d.
|
||||
DI_FLAGS_LOCK = 8, ///< Locked value.
|
||||
DI_FLAGS_ALLOC = 16, ///< Separately allocated.
|
||||
} DictItemFlags;
|
||||
|
||||
/// Structure representing a Dictionary
|
||||
struct dictvar_S {
|
||||
VarLockStatus dv_lock; ///< Whole dictionary lock status.
|
||||
ScopeType dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
|
||||
///< dictionary represents a scope (i.e. g:, l: …).
|
||||
int dv_refcount; ///< Reference count.
|
||||
int dv_copyID; ///< ID used when recursivery traversing a value.
|
||||
hashtab_T dv_hashtab; ///< Hashtab containing all items.
|
||||
dict_T *dv_copydict; ///< Copied dict used by deepcopy().
|
||||
dict_T *dv_used_next; ///< Next dictionary in used dictionaries list.
|
||||
dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list.
|
||||
QUEUE watchers; ///< Dictionary key watchers set by user code.
|
||||
};
|
||||
|
||||
/// Type used for script ID
|
||||
typedef int scid_T;
|
||||
|
||||
// Structure to hold info for a function that is currently being executed.
|
||||
typedef struct funccall_S funccall_T;
|
||||
|
||||
// Structure to hold info for a user function.
|
||||
typedef struct ufunc ufunc_T;
|
||||
|
||||
struct ufunc {
|
||||
int uf_varargs; ///< variable nr of arguments
|
||||
int uf_flags;
|
||||
int uf_calls; ///< nr of active calls
|
||||
bool uf_cleared; ///< func_clear() was already called
|
||||
garray_T uf_args; ///< arguments
|
||||
garray_T uf_lines; ///< function lines
|
||||
int uf_profiling; ///< true when func is being profiled
|
||||
// Profiling the function as a whole.
|
||||
int uf_tm_count; ///< nr of calls
|
||||
proftime_T uf_tm_total; ///< time spent in function + children
|
||||
proftime_T uf_tm_self; ///< time spent in function itself
|
||||
proftime_T uf_tm_children; ///< time spent in children this call
|
||||
// Profiling the function per line.
|
||||
int *uf_tml_count; ///< nr of times line was executed
|
||||
proftime_T *uf_tml_total; ///< time spent in a line + children
|
||||
proftime_T *uf_tml_self; ///< time spent in a line itself
|
||||
proftime_T uf_tml_start; ///< start time for current line
|
||||
proftime_T uf_tml_children; ///< time spent in children for this line
|
||||
proftime_T uf_tml_wait; ///< start wait time for current line
|
||||
int uf_tml_idx; ///< index of line being timed; -1 if none
|
||||
int uf_tml_execed; ///< line being timed was executed
|
||||
scid_T uf_script_ID; ///< ID of script where function was defined,
|
||||
// used for s: variables
|
||||
int uf_refcount; ///< reference count, see func_name_refcount()
|
||||
funccall_T *uf_scoped; ///< l: local variables for closure
|
||||
char_u uf_name[1]; ///< name of function (actually longer); can
|
||||
// start with <SNR>123_ (<SNR> is K_SPECIAL
|
||||
// KS_EXTRA KE_SNR)
|
||||
};
|
||||
|
||||
/// Maximum number of function arguments
|
||||
#define MAX_FUNC_ARGS 20
|
||||
|
||||
struct partial_S {
|
||||
int pt_refcount; ///< Reference count.
|
||||
char_u *pt_name; ///< Function name; when NULL use pt_func->name.
|
||||
ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with
|
||||
///< pt_name.
|
||||
bool pt_auto; ///< When true the partial was created by using dict.member
|
||||
///< in handle_subscript().
|
||||
int pt_argc; ///< Number of arguments.
|
||||
typval_T *pt_argv; ///< Arguments in allocated array.
|
||||
dict_T *pt_dict; ///< Dict for "self".
|
||||
};
|
||||
|
||||
/// Structure used for explicit stack while garbage collecting hash tables
|
||||
typedef struct ht_stack_S {
|
||||
hashtab_T *ht;
|
||||
struct ht_stack_S *prev;
|
||||
} ht_stack_T;
|
||||
|
||||
/// Structure used for explicit stack while garbage collecting lists
|
||||
typedef struct list_stack_S {
|
||||
list_T *list;
|
||||
struct list_stack_S *prev;
|
||||
} list_stack_T;
|
||||
|
||||
// In a hashtab item "hi_key" points to "di_key" in a dictitem.
|
||||
// This avoids adding a pointer to the hashtab item.
|
||||
|
||||
/// Convert a dictitem pointer to a hashitem key pointer
|
||||
#define DI2HIKEY(di) ((di)->di_key)
|
||||
|
||||
/// Convert a hashitem key pointer to a dictitem pointer
|
||||
#define HIKEY2DI(p) ((dictitem_T *)(p - offsetof(dictitem_T, di_key)))
|
||||
|
||||
/// Convert a hashitem value pointer to a dictitem pointer
|
||||
#define HIVAL2DI(p) \
|
||||
((dictitem_T *)(((char *)p) - offsetof(dictitem_T, di_tv)))
|
||||
|
||||
/// Convert a hashitem pointer to a dictitem pointer
|
||||
#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
|
||||
|
||||
/// Get the number of items in a list
|
||||
///
|
||||
/// @param[in] l List to check.
|
||||
static inline long tv_list_len(list_T *const l)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
if (l == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return l->lv_len;
|
||||
}
|
||||
|
||||
/// Empty string
|
||||
///
|
||||
/// Needed for hack which allows not allocating empty string and still not
|
||||
/// crashing when freeing it.
|
||||
extern const char *const tv_empty_string;
|
||||
|
||||
/// Specifies that free_unref_items() function has (not) been entered
|
||||
extern bool tv_in_free_unref_items;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/typval.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_EVAL_TYPVAL_H
|
@@ -242,7 +242,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "nvim/lib/kvec.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/eval/encode.h"
|
||||
#include "nvim/func_attr.h"
|
||||
#include "nvim/eval/typval_encode.h"
|
||||
|
@@ -11,7 +11,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "nvim/lib/kvec.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/func_attr.h"
|
||||
|
||||
/// Type of the stack entry
|
||||
|
Reference in New Issue
Block a user