mirror of
https://github.com/neovim/neovim.git
synced 2025-09-12 22:38:16 +00:00
*: Start hiding list implementation
Most of files, except for eval.c and eval/* were only processed by perl.
This commit is contained in:
@@ -798,7 +798,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
|||||||
|
|
||||||
tv_list_append(list, li);
|
tv_list_append(list, li);
|
||||||
}
|
}
|
||||||
list->lv_refcount++;
|
tv_list_ref(list);
|
||||||
|
|
||||||
tv->v_type = VAR_LIST;
|
tv->v_type = VAR_LIST;
|
||||||
tv->vval.v_list = list;
|
tv->vval.v_list = list;
|
||||||
|
@@ -673,7 +673,7 @@ static void on_channel_event(void **args)
|
|||||||
argv[1].v_type = VAR_LIST;
|
argv[1].v_type = VAR_LIST;
|
||||||
argv[1].v_lock = VAR_UNLOCKED;
|
argv[1].v_lock = VAR_UNLOCKED;
|
||||||
argv[1].vval.v_list = ev->received;
|
argv[1].vval.v_list = ev->received;
|
||||||
argv[1].vval.v_list->lv_refcount++;
|
tv_list_ref(argv[1].vval.v_list);
|
||||||
} else {
|
} else {
|
||||||
argv[1].v_type = VAR_NUMBER;
|
argv[1].v_type = VAR_NUMBER;
|
||||||
argv[1].v_lock = VAR_UNLOCKED;
|
argv[1].v_lock = VAR_UNLOCKED;
|
||||||
|
769
src/nvim/eval.c
769
src/nvim/eval.c
File diff suppressed because it is too large
Load Diff
@@ -61,7 +61,7 @@ static inline void create_special_dict(typval_T *const rettv,
|
|||||||
type_di->di_tv.v_type = VAR_LIST;
|
type_di->di_tv.v_type = VAR_LIST;
|
||||||
type_di->di_tv.v_lock = VAR_UNLOCKED;
|
type_di->di_tv.v_lock = VAR_UNLOCKED;
|
||||||
type_di->di_tv.vval.v_list = (list_T *) eval_msgpack_type_lists[type];
|
type_di->di_tv.vval.v_list = (list_T *) eval_msgpack_type_lists[type];
|
||||||
type_di->di_tv.vval.v_list->lv_refcount++;
|
tv_list_ref(type_di->di_tv.vval.v_list);
|
||||||
tv_dict_add(dict, type_di);
|
tv_dict_add(dict, type_di);
|
||||||
dictitem_T *const val_di = tv_dict_item_alloc_len(S_LEN("_VAL"));
|
dictitem_T *const val_di = tv_dict_item_alloc_len(S_LEN("_VAL"));
|
||||||
val_di->di_tv = val;
|
val_di->di_tv = val;
|
||||||
@@ -234,7 +234,7 @@ list_T *decode_create_map_special_dict(typval_T *const ret_tv)
|
|||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
list_T *const list = tv_list_alloc();
|
list_T *const list = tv_list_alloc();
|
||||||
list->lv_refcount++;
|
tv_list_ref(list);
|
||||||
create_special_dict(ret_tv, kMPMap, ((typval_T) {
|
create_special_dict(ret_tv, kMPMap, ((typval_T) {
|
||||||
.v_type = VAR_LIST,
|
.v_type = VAR_LIST,
|
||||||
.v_lock = VAR_UNLOCKED,
|
.v_lock = VAR_UNLOCKED,
|
||||||
@@ -270,7 +270,7 @@ typval_T decode_string(const char *const s, const size_t len,
|
|||||||
: (bool)hasnul);
|
: (bool)hasnul);
|
||||||
if (really_hasnul) {
|
if (really_hasnul) {
|
||||||
list_T *const list = tv_list_alloc();
|
list_T *const list = tv_list_alloc();
|
||||||
list->lv_refcount++;
|
tv_list_ref(list);
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
create_special_dict(&tv, binary ? kMPBinary : kMPString, ((typval_T) {
|
create_special_dict(&tv, binary ? kMPBinary : kMPString, ((typval_T) {
|
||||||
.v_type = VAR_LIST,
|
.v_type = VAR_LIST,
|
||||||
@@ -849,7 +849,7 @@ json_decode_string_cycle_start:
|
|||||||
}
|
}
|
||||||
case '[': {
|
case '[': {
|
||||||
list_T *list = tv_list_alloc();
|
list_T *list = tv_list_alloc();
|
||||||
list->lv_refcount++;
|
tv_list_ref(list);
|
||||||
typval_T tv = {
|
typval_T tv = {
|
||||||
.v_type = VAR_LIST,
|
.v_type = VAR_LIST,
|
||||||
.v_lock = VAR_UNLOCKED,
|
.v_lock = VAR_UNLOCKED,
|
||||||
@@ -970,7 +970,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
list_T *const list = tv_list_alloc();
|
list_T *const list = tv_list_alloc();
|
||||||
list->lv_refcount++;
|
tv_list_ref(list);
|
||||||
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
||||||
.v_type = VAR_LIST,
|
.v_type = VAR_LIST,
|
||||||
.v_lock = VAR_UNLOCKED,
|
.v_lock = VAR_UNLOCKED,
|
||||||
@@ -993,7 +993,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
list_T *const list = tv_list_alloc();
|
list_T *const list = tv_list_alloc();
|
||||||
list->lv_refcount++;
|
tv_list_ref(list);
|
||||||
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
||||||
.v_type = VAR_LIST,
|
.v_type = VAR_LIST,
|
||||||
.v_lock = VAR_UNLOCKED,
|
.v_lock = VAR_UNLOCKED,
|
||||||
@@ -1039,7 +1039,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
|||||||
}
|
}
|
||||||
case MSGPACK_OBJECT_ARRAY: {
|
case MSGPACK_OBJECT_ARRAY: {
|
||||||
list_T *const list = tv_list_alloc();
|
list_T *const list = tv_list_alloc();
|
||||||
list->lv_refcount++;
|
tv_list_ref(list);
|
||||||
*rettv = (typval_T) {
|
*rettv = (typval_T) {
|
||||||
.v_type = VAR_LIST,
|
.v_type = VAR_LIST,
|
||||||
.v_lock = VAR_UNLOCKED,
|
.v_lock = VAR_UNLOCKED,
|
||||||
@@ -1110,7 +1110,7 @@ msgpack_to_vim_generic_map: {}
|
|||||||
}
|
}
|
||||||
case MSGPACK_OBJECT_EXT: {
|
case MSGPACK_OBJECT_EXT: {
|
||||||
list_T *const list = tv_list_alloc();
|
list_T *const list = tv_list_alloc();
|
||||||
list->lv_refcount++;
|
tv_list_ref(list);
|
||||||
tv_list_append_number(list, mobj.via.ext.type);
|
tv_list_append_number(list, mobj.via.ext.type);
|
||||||
list_T *const ext_val_list = tv_list_alloc();
|
list_T *const ext_val_list = tv_list_alloc();
|
||||||
tv_list_append_list(list, ext_val_list);
|
tv_list_append_list(list, ext_val_list);
|
||||||
|
@@ -66,7 +66,7 @@ listitem_T *tv_list_item_alloc(void)
|
|||||||
void tv_list_item_free(listitem_T *const item)
|
void tv_list_item_free(listitem_T *const item)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
tv_clear(&item->li_tv);
|
tv_clear(TV_LIST_ITEM_TV(item));
|
||||||
xfree(item);
|
xfree(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +326,7 @@ void tv_list_append_tv(list_T *const l, typval_T *const tv)
|
|||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
listitem_T *const li = tv_list_item_alloc();
|
listitem_T *const li = tv_list_item_alloc();
|
||||||
tv_copy(tv, &li->li_tv);
|
tv_copy(tv, TV_LIST_ITEM_TV(li));
|
||||||
tv_list_append(l, li);
|
tv_list_append(l, li);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,12 +339,12 @@ void tv_list_append_list(list_T *const list, list_T *const itemlist)
|
|||||||
{
|
{
|
||||||
listitem_T *const li = tv_list_item_alloc();
|
listitem_T *const li = tv_list_item_alloc();
|
||||||
|
|
||||||
li->li_tv.v_type = VAR_LIST;
|
TV_LIST_ITEM_TV(li)->v_type = VAR_LIST;
|
||||||
li->li_tv.v_lock = VAR_UNLOCKED;
|
TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED;
|
||||||
li->li_tv.vval.v_list = itemlist;
|
TV_LIST_ITEM_TV(li)->vval.v_list = itemlist;
|
||||||
tv_list_append(list, li);
|
tv_list_append(list, li);
|
||||||
if (itemlist != NULL) {
|
if (itemlist != NULL) {
|
||||||
itemlist->lv_refcount++;
|
tv_list_ref(itemlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,9 +357,9 @@ void tv_list_append_dict(list_T *const list, dict_T *const dict)
|
|||||||
{
|
{
|
||||||
listitem_T *const li = tv_list_item_alloc();
|
listitem_T *const li = tv_list_item_alloc();
|
||||||
|
|
||||||
li->li_tv.v_type = VAR_DICT;
|
TV_LIST_ITEM_TV(li)->v_type = VAR_DICT;
|
||||||
li->li_tv.v_lock = VAR_UNLOCKED;
|
TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED;
|
||||||
li->li_tv.vval.v_dict = dict;
|
TV_LIST_ITEM_TV(li)->vval.v_dict = dict;
|
||||||
tv_list_append(list, li);
|
tv_list_append(list, li);
|
||||||
if (dict != NULL) {
|
if (dict != NULL) {
|
||||||
dict->dv_refcount++;
|
dict->dv_refcount++;
|
||||||
@@ -399,9 +399,9 @@ void tv_list_append_allocated_string(list_T *const l, char *const str)
|
|||||||
listitem_T *const li = tv_list_item_alloc();
|
listitem_T *const li = tv_list_item_alloc();
|
||||||
|
|
||||||
tv_list_append(l, li);
|
tv_list_append(l, li);
|
||||||
li->li_tv.v_type = VAR_STRING;
|
TV_LIST_ITEM_TV(li)->v_type = VAR_STRING;
|
||||||
li->li_tv.v_lock = VAR_UNLOCKED;
|
TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED;
|
||||||
li->li_tv.vval.v_string = (char_u *)str;
|
TV_LIST_ITEM_TV(li)->vval.v_string = (char_u *)str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append number to the list
|
/// Append number to the list
|
||||||
@@ -412,9 +412,9 @@ void tv_list_append_allocated_string(list_T *const l, char *const str)
|
|||||||
void tv_list_append_number(list_T *const l, const varnumber_T n)
|
void tv_list_append_number(list_T *const l, const varnumber_T n)
|
||||||
{
|
{
|
||||||
listitem_T *const li = tv_list_item_alloc();
|
listitem_T *const li = tv_list_item_alloc();
|
||||||
li->li_tv.v_type = VAR_NUMBER;
|
TV_LIST_ITEM_TV(li)->v_type = VAR_NUMBER;
|
||||||
li->li_tv.v_lock = VAR_UNLOCKED;
|
TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED;
|
||||||
li->li_tv.vval.v_number = n;
|
TV_LIST_ITEM_TV(li)->vval.v_number = n;
|
||||||
tv_list_append(l, li);
|
tv_list_append(l, li);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,33 +439,32 @@ list_T *tv_list_copy(const vimconv_T *const conv, list_T *const orig,
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_T *copy = tv_list_alloc();
|
list_T *copy = tv_list_alloc();
|
||||||
|
tv_list_ref(copy);
|
||||||
if (copyID != 0) {
|
if (copyID != 0) {
|
||||||
// Do this before adding the items, because one of the items may
|
// Do this before adding the items, because one of the items may
|
||||||
// refer back to this list.
|
// refer back to this list.
|
||||||
orig->lv_copyID = copyID;
|
orig->lv_copyID = copyID;
|
||||||
orig->lv_copylist = copy;
|
orig->lv_copylist = copy;
|
||||||
}
|
}
|
||||||
listitem_T *item;
|
TV_LIST_ITER(orig, item, {
|
||||||
for (item = orig->lv_first; item != NULL && !got_int;
|
|
||||||
item = item->li_next) {
|
|
||||||
listitem_T *const ni = tv_list_item_alloc();
|
listitem_T *const ni = tv_list_item_alloc();
|
||||||
if (deep) {
|
if (deep) {
|
||||||
if (var_item_copy(conv, &item->li_tv, &ni->li_tv, deep, copyID) == FAIL) {
|
if (var_item_copy(conv, TV_LIST_ITEM_TV(item), TV_LIST_ITEM_TV(ni),
|
||||||
|
deep, copyID) == FAIL) {
|
||||||
xfree(ni);
|
xfree(ni);
|
||||||
break;
|
goto tv_list_copy_error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tv_copy(&item->li_tv, &ni->li_tv);
|
tv_copy(TV_LIST_ITEM_TV(item), TV_LIST_ITEM_TV(ni));
|
||||||
}
|
}
|
||||||
tv_list_append(copy, ni);
|
tv_list_append(copy, ni);
|
||||||
}
|
});
|
||||||
copy->lv_refcount++;
|
|
||||||
if (item != NULL) {
|
|
||||||
tv_list_unref(copy);
|
|
||||||
copy = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
|
|
||||||
|
tv_list_copy_error:
|
||||||
|
tv_list_unref(copy);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extend first list with the second
|
/// Extend first list with the second
|
||||||
@@ -475,17 +474,17 @@ list_T *tv_list_copy(const vimconv_T *const conv, list_T *const orig,
|
|||||||
/// @param[in] bef If not NULL, extends before this item.
|
/// @param[in] bef If not NULL, extends before this item.
|
||||||
void tv_list_extend(list_T *const l1, list_T *const l2,
|
void tv_list_extend(list_T *const l1, list_T *const l2,
|
||||||
listitem_T *const bef)
|
listitem_T *const bef)
|
||||||
FUNC_ATTR_NONNULL_ARG(1, 2)
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
int todo = l2->lv_len;
|
int todo = tv_list_len(l2);
|
||||||
listitem_T *const befbef = (bef == NULL ? NULL : bef->li_prev);
|
listitem_T *const befbef = (bef == NULL ? NULL : bef->li_prev);
|
||||||
listitem_T *const saved_next = (befbef == NULL ? NULL : befbef->li_next);
|
listitem_T *const saved_next = (befbef == NULL ? NULL : befbef->li_next);
|
||||||
// We also quit the loop when we have inserted the original item count of
|
// We also quit the loop when we have inserted the original item count of
|
||||||
// the list, avoid a hang when we extend a list with itself.
|
// the list, avoid a hang when we extend a list with itself.
|
||||||
for (listitem_T *item = l2->lv_first
|
for (listitem_T *item = tv_list_first(l2)
|
||||||
; item != NULL && --todo >= 0
|
; item != NULL && todo--
|
||||||
; item = (item == befbef ? saved_next : item->li_next)) {
|
; item = (item == befbef ? saved_next : item->li_next)) {
|
||||||
tv_list_insert_tv(l1, &item->li_tv, bef);
|
tv_list_insert_tv(l1, TV_LIST_ITEM_TV(item), bef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,13 +539,12 @@ static int list_join_inner(garray_T *const gap, list_T *const l,
|
|||||||
{
|
{
|
||||||
size_t sumlen = 0;
|
size_t sumlen = 0;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
listitem_T *item;
|
|
||||||
|
|
||||||
// Stringify each item in the list.
|
// Stringify each item in the list.
|
||||||
for (item = l->lv_first; item != NULL && !got_int; item = item->li_next) {
|
TV_LIST_ITER(l, item, {
|
||||||
char *s;
|
char *s;
|
||||||
size_t len;
|
size_t len;
|
||||||
s = encode_tv2echo(&item->li_tv, &len);
|
s = encode_tv2echo(TV_LIST_ITEM_TV(item), &len);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
@@ -557,7 +555,7 @@ static int list_join_inner(garray_T *const gap, list_T *const l,
|
|||||||
p->tofree = p->s = (char_u *)s;
|
p->tofree = p->s = (char_u *)s;
|
||||||
|
|
||||||
line_breakcheck();
|
line_breakcheck();
|
||||||
}
|
});
|
||||||
|
|
||||||
// Allocate result buffer with its total size, avoid re-allocation and
|
// Allocate result buffer with its total size, avoid re-allocation and
|
||||||
// multiple copy operations. Add 2 for a tailing ']' and NUL.
|
// multiple copy operations. Add 2 for a tailing ']' and NUL.
|
||||||
@@ -591,16 +589,16 @@ static int list_join_inner(garray_T *const gap, list_T *const l,
|
|||||||
///
|
///
|
||||||
/// @return OK in case of success, FAIL otherwise.
|
/// @return OK in case of success, FAIL otherwise.
|
||||||
int tv_list_join(garray_T *const gap, list_T *const l, const char *const sep)
|
int tv_list_join(garray_T *const gap, list_T *const l, const char *const sep)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
if (l->lv_len < 1) {
|
if (!tv_list_len(l)) {
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
garray_T join_ga;
|
garray_T join_ga;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
ga_init(&join_ga, (int)sizeof(Join), l->lv_len);
|
ga_init(&join_ga, (int)sizeof(Join), tv_list_len(l));
|
||||||
retval = list_join_inner(gap, l, sep, &join_ga);
|
retval = list_join_inner(gap, l, sep, &join_ga);
|
||||||
|
|
||||||
#define FREE_JOIN_TOFREE(join) xfree((join)->tofree)
|
#define FREE_JOIN_TOFREE(join) xfree((join)->tofree)
|
||||||
@@ -632,11 +630,13 @@ bool tv_list_equal(list_T *const l1, list_T *const l2, const bool ic,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
listitem_T *item1 = l1->lv_first;
|
listitem_T *item1 = tv_list_first(l1);
|
||||||
listitem_T *item2 = l2->lv_first;
|
listitem_T *item2 = tv_list_first(l2);
|
||||||
for (; item1 != NULL && item2 != NULL
|
for (; item1 != NULL && item2 != NULL
|
||||||
; item1 = item1->li_next, item2 = item2->li_next) {
|
; item1 = TV_LIST_ITEM_NEXT(l1, item1),
|
||||||
if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive)) {
|
item2 = TV_LIST_ITEM_NEXT(n2, item2)) {
|
||||||
|
if (!tv_equal(TV_LIST_ITEM_TV(item1), TV_LIST_ITEM_TV(item2), ic,
|
||||||
|
recursive)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -662,13 +662,8 @@ listitem_T *tv_list_find(list_T *const l, int n)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negative index is relative to the end.
|
n = tv_list_uidx(l, n);
|
||||||
if (n < 0) {
|
if (n == -1) {
|
||||||
n = l->lv_len + n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for index out of range.
|
|
||||||
if (n < 0 || n >= l->lv_len) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -740,7 +735,7 @@ varnumber_T tv_list_find_nr(list_T *const l, const int n, bool *const ret_error)
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return tv_get_number_chk(&li->li_tv, ret_error);
|
return tv_get_number_chk(TV_LIST_ITEM_TV(li), ret_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get list item l[n] as a string
|
/// Get list item l[n] as a string
|
||||||
@@ -757,7 +752,7 @@ const char *tv_list_find_str(list_T *const l, const int n)
|
|||||||
emsgf(_(e_listidx), (int64_t)n);
|
emsgf(_(e_listidx), (int64_t)n);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return tv_get_string(&li->li_tv);
|
return tv_get_string(TV_LIST_ITEM_TV(li));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Locate item in a list and return its index
|
/// Locate item in a list and return its index
|
||||||
@@ -772,16 +767,15 @@ long tv_list_idx_of_item(const list_T *const l, const listitem_T *const item)
|
|||||||
if (l == NULL) {
|
if (l == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
long idx = 0;
|
int idx = 0;
|
||||||
const listitem_T *li;
|
TV_LIST_ITER_CONST(l, li, {
|
||||||
for (li = l->lv_first; li != NULL && li != item; li = li->li_next) {
|
if (li == item) {
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
if (li == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
idx++;
|
||||||
|
});
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
//{{{1 Dictionaries
|
//{{{1 Dictionaries
|
||||||
//{{{2 Dictionary watchers
|
//{{{2 Dictionary watchers
|
||||||
@@ -1339,7 +1333,7 @@ int tv_dict_add_list(dict_T *const d, const char *const key,
|
|||||||
item->di_tv.v_lock = VAR_UNLOCKED;
|
item->di_tv.v_lock = VAR_UNLOCKED;
|
||||||
item->di_tv.v_type = VAR_LIST;
|
item->di_tv.v_type = VAR_LIST;
|
||||||
item->di_tv.vval.v_list = list;
|
item->di_tv.vval.v_list = list;
|
||||||
list->lv_refcount++;
|
tv_list_ref(list);
|
||||||
if (tv_dict_add(d, item) == FAIL) {
|
if (tv_dict_add(d, item) == FAIL) {
|
||||||
tv_dict_item_free(item);
|
tv_dict_item_free(item);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -1677,7 +1671,7 @@ list_T *tv_list_alloc_ret(typval_T *const ret_tv)
|
|||||||
ret_tv->vval.v_list = l;
|
ret_tv->vval.v_list = l;
|
||||||
ret_tv->v_type = VAR_LIST;
|
ret_tv->v_type = VAR_LIST;
|
||||||
ret_tv->v_lock = VAR_UNLOCKED;
|
ret_tv->v_lock = VAR_UNLOCKED;
|
||||||
l->lv_refcount++;
|
tv_list_ref(l);
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2027,7 +2021,7 @@ void tv_copy(typval_T *const from, typval_T *const to)
|
|||||||
}
|
}
|
||||||
case VAR_LIST: {
|
case VAR_LIST: {
|
||||||
if (from->vval.v_list != NULL) {
|
if (from->vval.v_list != NULL) {
|
||||||
to->vval.v_list->lv_refcount++;
|
tv_list_ref(to->vval.v_list);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2084,9 +2078,9 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock)
|
|||||||
CHANGE_LOCK(lock, l->lv_lock);
|
CHANGE_LOCK(lock, l->lv_lock);
|
||||||
if (deep < 0 || deep > 1) {
|
if (deep < 0 || deep > 1) {
|
||||||
// Recursive: lock/unlock the items the List contains.
|
// Recursive: lock/unlock the items the List contains.
|
||||||
for (listitem_T *li = l->lv_first; li != NULL; li = li->li_next) {
|
TV_LIST_ITER(l, li, {
|
||||||
tv_item_lock(&li->li_tv, deep - 1, lock);
|
tv_item_lock(TV_LIST_ITEM_TV(li), deep - 1, lock);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2122,6 +2116,8 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock)
|
|||||||
|
|
||||||
/// Check whether VimL value is locked itself or refers to a locked container
|
/// Check whether VimL value is locked itself or refers to a locked container
|
||||||
///
|
///
|
||||||
|
/// @warning Fixed container is not the same as locked.
|
||||||
|
///
|
||||||
/// @param[in] tv Value to check.
|
/// @param[in] tv Value to check.
|
||||||
///
|
///
|
||||||
/// @return True if value is locked, false otherwise.
|
/// @return True if value is locked, false otherwise.
|
||||||
@@ -2130,8 +2126,7 @@ bool tv_islocked(const typval_T *const tv)
|
|||||||
{
|
{
|
||||||
return ((tv->v_lock == VAR_LOCKED)
|
return ((tv->v_lock == VAR_LOCKED)
|
||||||
|| (tv->v_type == VAR_LIST
|
|| (tv->v_type == VAR_LIST
|
||||||
&& tv->vval.v_list != NULL
|
&& (tv_list_locked(tv->vval.v_list) == VAR_LOCKED))
|
||||||
&& (tv->vval.v_list->lv_lock == VAR_LOCKED))
|
|
||||||
|| (tv->v_type == VAR_DICT
|
|| (tv->v_type == VAR_DICT
|
||||||
&& tv->vval.v_dict != NULL
|
&& tv->vval.v_dict != NULL
|
||||||
&& (tv->vval.v_dict->dv_lock == VAR_LOCKED)));
|
&& (tv->vval.v_dict->dv_lock == VAR_LOCKED)));
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "nvim/types.h"
|
#include "nvim/types.h"
|
||||||
#include "nvim/hashtab.h"
|
#include "nvim/hashtab.h"
|
||||||
@@ -284,9 +285,6 @@ typedef struct list_stack_S {
|
|||||||
#define TV_DICT_HI2DI(hi) \
|
#define TV_DICT_HI2DI(hi) \
|
||||||
((dictitem_T *)((hi)->hi_key - offsetof(dictitem_T, di_key)))
|
((dictitem_T *)((hi)->hi_key - offsetof(dictitem_T, di_key)))
|
||||||
|
|
||||||
static inline void tv_list_ref(list_T *const l)
|
|
||||||
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
|
||||||
|
|
||||||
/// Increase reference count for a given list
|
/// Increase reference count for a given list
|
||||||
///
|
///
|
||||||
/// Does nothing for NULL lists.
|
/// Does nothing for NULL lists.
|
||||||
@@ -332,13 +330,13 @@ static inline void tv_list_set_lock(list_T *const l,
|
|||||||
l->lv_lock = lock;
|
l->lv_lock = lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline long tv_list_len(const list_T *const l)
|
static inline int tv_list_len(const list_T *const l)
|
||||||
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/// Get the number of items in a list
|
/// Get the number of items in a list
|
||||||
///
|
///
|
||||||
/// @param[in] l List to check.
|
/// @param[in] l List to check.
|
||||||
static inline long tv_list_len(const list_T *const l)
|
static inline int tv_list_len(const list_T *const l)
|
||||||
{
|
{
|
||||||
if (l == NULL) {
|
if (l == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -346,6 +344,29 @@ static inline long tv_list_len(const list_T *const l)
|
|||||||
return l->lv_len;
|
return l->lv_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int tv_list_uidx(const list_T *const l, int n)
|
||||||
|
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
/// Normalize index: that is, return either -1 or non-negative index
|
||||||
|
///
|
||||||
|
/// @param[in] l List to intex. Used to get length.
|
||||||
|
/// @param[in] n List index, possibly negative.
|
||||||
|
///
|
||||||
|
/// @return -1 or list index in range [0, tv_list_len(l)).
|
||||||
|
static inline int tv_list_uidx(const list_T *const l, int n)
|
||||||
|
{
|
||||||
|
// Negative index is relative to the end.
|
||||||
|
if (n < 0) {
|
||||||
|
n += tv_list_len(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for index out of range.
|
||||||
|
if (n < 0 || n >= tv_list_len(l)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
static inline listitem_T *tv_list_first(const list_T *const l)
|
static inline listitem_T *tv_list_first(const list_T *const l)
|
||||||
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
@@ -427,7 +448,7 @@ extern bool tv_in_free_unref_items;
|
|||||||
do { \
|
do { \
|
||||||
modifier list_T *const l_ = (l); \
|
modifier list_T *const l_ = (l); \
|
||||||
if (l_ != NULL) { \
|
if (l_ != NULL) { \
|
||||||
for (modifier listitem_T *const li = l_->lv_first; \
|
for (modifier listitem_T *li = l_->lv_first; \
|
||||||
li != NULL; li = li->li_next) { \
|
li != NULL; li = li->li_next) { \
|
||||||
code \
|
code \
|
||||||
} \
|
} \
|
||||||
|
@@ -306,7 +306,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
|
|||||||
case kObjectTypeArray: {
|
case kObjectTypeArray: {
|
||||||
cur.tv->v_type = VAR_LIST;
|
cur.tv->v_type = VAR_LIST;
|
||||||
cur.tv->vval.v_list = tv_list_alloc();
|
cur.tv->vval.v_list = tv_list_alloc();
|
||||||
cur.tv->vval.v_list->lv_refcount++;
|
tv_list_ref(cur.tv->vval.v_list);
|
||||||
if (table_props.maxidx != 0) {
|
if (table_props.maxidx != 0) {
|
||||||
cur.container = true;
|
cur.container = true;
|
||||||
cur.idx = lua_gettop(lstate);
|
cur.idx = lua_gettop(lstate);
|
||||||
|
@@ -2568,7 +2568,7 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
|
|||||||
for (size_t i = 0; i < reg->y_size; i++) {
|
for (size_t i = 0; i < reg->y_size; i++) {
|
||||||
tv_list_append_string(list, (const char *)reg->y_array[i], -1);
|
tv_list_append_string(list, (const char *)reg->y_array[i], -1);
|
||||||
}
|
}
|
||||||
list->lv_lock = VAR_FIXED;
|
tv_list_set_lock(list, VAR_FIXED);
|
||||||
tv_dict_add_list(dict, S_LEN("regcontents"), list);
|
tv_dict_add_list(dict, S_LEN("regcontents"), list);
|
||||||
|
|
||||||
// the register type
|
// the register type
|
||||||
|
@@ -42,10 +42,6 @@ describe('NULL', function()
|
|||||||
describe('list', function()
|
describe('list', function()
|
||||||
-- Incorrect behaviour
|
-- Incorrect behaviour
|
||||||
|
|
||||||
-- FIXME add() should not return 1 at all
|
|
||||||
null_expr_test('does not crash add()', 'add(L, 0)', 0, 1)
|
|
||||||
null_expr_test('does not crash extend()', 'extend(L, [1])', 'E742: Cannot change value of extend() argument', 0)
|
|
||||||
null_expr_test('does not crash extend() (second position)', 'extend([1], L)', 0, {1})
|
|
||||||
-- FIXME should be accepted by inputlist()
|
-- FIXME should be accepted by inputlist()
|
||||||
null_expr_test('is accepted as an empty list by inputlist()',
|
null_expr_test('is accepted as an empty list by inputlist()',
|
||||||
'[feedkeys("\\n"), inputlist(L)]', 'E686: Argument of inputlist() must be a List', {0, 0})
|
'[feedkeys("\\n"), inputlist(L)]', 'E686: Argument of inputlist() must be a List', {0, 0})
|
||||||
@@ -53,18 +49,12 @@ describe('NULL', function()
|
|||||||
null_expr_test('is accepted as an empty list by writefile()',
|
null_expr_test('is accepted as an empty list by writefile()',
|
||||||
('[writefile(L, "%s"), readfile("%s")]'):format(tmpfname, tmpfname),
|
('[writefile(L, "%s"), readfile("%s")]'):format(tmpfname, tmpfname),
|
||||||
'E484: Can\'t open file ' .. tmpfname, {0, {}})
|
'E484: Can\'t open file ' .. tmpfname, {0, {}})
|
||||||
-- FIXME should give error message
|
|
||||||
null_expr_test('does not crash remove()', 'remove(L, 0)', 0, 0)
|
|
||||||
-- FIXME should return 0
|
-- FIXME should return 0
|
||||||
null_expr_test('is accepted by setqflist()', 'setqflist(L)', 0, -1)
|
null_expr_test('is accepted by setqflist()', 'setqflist(L)', 0, -1)
|
||||||
-- FIXME should return 0
|
-- FIXME should return 0
|
||||||
null_expr_test('is accepted by setloclist()', 'setloclist(1, L)', 0, -1)
|
null_expr_test('is accepted by setloclist()', 'setloclist(1, L)', 0, -1)
|
||||||
-- FIXME should return 0
|
-- FIXME should return 0
|
||||||
null_expr_test('is accepted by setmatches()', 'setmatches(L)', 0, -1)
|
null_expr_test('is accepted by setmatches()', 'setmatches(L)', 0, -1)
|
||||||
-- FIXME should return empty list or error out
|
|
||||||
null_expr_test('is accepted by sort()', 'sort(L)', 0, 0)
|
|
||||||
-- FIXME Should return 1
|
|
||||||
null_expr_test('is accepted by sort()', 'sort(L) is L', 0, 0)
|
|
||||||
-- FIXME should not error out
|
-- FIXME should not error out
|
||||||
null_test('is accepted by :cexpr', 'cexpr L', 'Vim(cexpr):E777: String or List expected')
|
null_test('is accepted by :cexpr', 'cexpr L', 'Vim(cexpr):E777: String or List expected')
|
||||||
-- FIXME should not error out
|
-- FIXME should not error out
|
||||||
@@ -80,13 +70,6 @@ describe('NULL', function()
|
|||||||
-- FIXME Should return 1
|
-- FIXME Should return 1
|
||||||
null_expr_test('is not locked', 'islocked("v:_null_list")', 0, 0)
|
null_expr_test('is not locked', 'islocked("v:_null_list")', 0, 0)
|
||||||
|
|
||||||
-- Crashes
|
|
||||||
|
|
||||||
-- null_expr_test('does not crash setreg', 'setreg("x", L)', 0, 0)
|
|
||||||
-- null_expr_test('does not crash setline', 'setline(1, L)', 0, 0)
|
|
||||||
-- null_expr_test('does not crash system()', 'system("cat", L)', 0, '')
|
|
||||||
-- null_expr_test('does not crash systemlist()', 'systemlist("cat", L)', 0, {})
|
|
||||||
|
|
||||||
-- Correct behaviour
|
-- Correct behaviour
|
||||||
null_expr_test('does not crash append()', 'append(1, L)', 0, 0, function()
|
null_expr_test('does not crash append()', 'append(1, L)', 0, 0, function()
|
||||||
eq({''}, curbufmeths.get_lines(0, -1, false))
|
eq({''}, curbufmeths.get_lines(0, -1, false))
|
||||||
@@ -122,6 +105,22 @@ describe('NULL', function()
|
|||||||
null_expr_test('counts correctly', 'count([L], L)', 0, 1)
|
null_expr_test('counts correctly', 'count([L], L)', 0, 1)
|
||||||
null_expr_test('makes map() return v:_null_list', 'map(L, "v:val") is# L', 0, 1)
|
null_expr_test('makes map() return v:_null_list', 'map(L, "v:val") is# L', 0, 1)
|
||||||
null_expr_test('makes filter() return v:_null_list', 'filter(L, "1") is# L', 0, 1)
|
null_expr_test('makes filter() return v:_null_list', 'filter(L, "1") is# L', 0, 1)
|
||||||
|
null_test('is treated by :let as empty list', ':let [l] = L', 'Vim(let):E688: More targets than List items')
|
||||||
|
-- FIXME fix test results
|
||||||
|
null_expr_test('does not crash add()', 'add(L, 0)', 0, 1)
|
||||||
|
null_expr_test('makes insert() error out', 'insert(L, 1)', '', nil)
|
||||||
|
null_expr_test('does not crash remove()', 'remove(L, 0)', 0, 0)
|
||||||
|
null_expr_test('makes reverse() error out', 'reverse(L)', '', nil)
|
||||||
|
null_expr_test('is accepted by sort()', 'sort(L)', 0, 0)
|
||||||
|
null_expr_test('makes sort() return itself', 'sort(L) is L', 0, 0)
|
||||||
|
null_expr_test('does not crash extend()', 'extend(L, [1])', 'E742: Cannot change value of extend() argument', 0)
|
||||||
|
null_expr_test('does not crash extend() (second position)', 'extend([1], L)', 0, {1})
|
||||||
|
null_expr_test('makes join() return empty string', 'join(L, "")', 0, '')
|
||||||
|
null_expr_test('makes msgpackdump() return empty list', 'msgpackdump(L)', 0, {})
|
||||||
|
null_expr_test('does not crash system()', 'system("cat", L)', 0, '')
|
||||||
|
null_expr_test('does not crash setreg', 'setreg("x", L)', 0, 0)
|
||||||
|
null_expr_test('does not crash systemlist()', 'systemlist("cat", L)', 0, {})
|
||||||
|
null_expr_test('does not crash setline', 'setline(1, L)', 0, 0)
|
||||||
end)
|
end)
|
||||||
describe('dict', function()
|
describe('dict', function()
|
||||||
it('does not crash when indexing NULL dict', function()
|
it('does not crash when indexing NULL dict', function()
|
||||||
|
Reference in New Issue
Block a user