mirror of
https://github.com/vim/vim.git
synced 2025-10-23 08:44:20 -04:00
patch 9.1.1232: Vim script is missing the tuple data type
Problem: Vim script is missing the tuple data type Solution: Add support for the tuple data type (Yegappan Lakshmanan) closes: #16776 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
adb703e1b9
commit
9cb865e95b
185
src/gc.c
185
src/gc.c
@@ -122,31 +122,31 @@ garbage_collect(int testing)
|
||||
// buffer-local variables
|
||||
FOR_ALL_BUFFERS(buf)
|
||||
abort = abort || set_ref_in_item(&buf->b_bufvar.di_tv, copyID,
|
||||
NULL, NULL);
|
||||
NULL, NULL, NULL);
|
||||
|
||||
// window-local variables
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp)
|
||||
abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
|
||||
NULL, NULL);
|
||||
NULL, NULL, NULL);
|
||||
// window-local variables in autocmd windows
|
||||
for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
|
||||
if (aucmd_win[i].auc_win != NULL)
|
||||
abort = abort || set_ref_in_item(
|
||||
&aucmd_win[i].auc_win->w_winvar.di_tv, copyID, NULL, NULL);
|
||||
&aucmd_win[i].auc_win->w_winvar.di_tv, copyID, NULL, NULL, NULL);
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
FOR_ALL_POPUPWINS(wp)
|
||||
abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
|
||||
NULL, NULL);
|
||||
NULL, NULL, NULL);
|
||||
FOR_ALL_TABPAGES(tp)
|
||||
FOR_ALL_POPUPWINS_IN_TAB(tp, wp)
|
||||
abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
|
||||
NULL, NULL);
|
||||
NULL, NULL, NULL);
|
||||
#endif
|
||||
|
||||
// tabpage-local variables
|
||||
FOR_ALL_TABPAGES(tp)
|
||||
abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID,
|
||||
NULL, NULL);
|
||||
NULL, NULL, NULL);
|
||||
// global variables
|
||||
abort = abort || garbage_collect_globvars(copyID);
|
||||
|
||||
@@ -269,6 +269,9 @@ free_unref_items(int copyID)
|
||||
// Go through the list of lists and free items without this copyID.
|
||||
did_free |= list_free_nonref(copyID);
|
||||
|
||||
// Go through the list of tuples and free items without this copyID.
|
||||
did_free |= tuple_free_nonref(copyID);
|
||||
|
||||
// Go through the list of objects and free items without this copyID.
|
||||
did_free |= object_free_nonref(copyID);
|
||||
|
||||
@@ -291,6 +294,7 @@ free_unref_items(int copyID)
|
||||
object_free_items(copyID);
|
||||
dict_free_items(copyID);
|
||||
list_free_items(copyID);
|
||||
tuple_free_items(copyID);
|
||||
|
||||
#ifdef FEAT_JOB_CHANNEL
|
||||
// Go through the list of jobs and free items without the copyID. This
|
||||
@@ -314,7 +318,11 @@ free_unref_items(int copyID)
|
||||
* Returns TRUE if setting references failed somehow.
|
||||
*/
|
||||
int
|
||||
set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack)
|
||||
set_ref_in_ht(
|
||||
hashtab_T *ht,
|
||||
int copyID,
|
||||
list_stack_T **list_stack,
|
||||
tuple_stack_T **tuple_stack)
|
||||
{
|
||||
int todo;
|
||||
int abort = FALSE;
|
||||
@@ -336,8 +344,9 @@ set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack)
|
||||
if (!HASHITEM_EMPTY(hi))
|
||||
{
|
||||
--todo;
|
||||
abort = abort || set_ref_in_item(&HI2DI(hi)->di_tv, copyID,
|
||||
&ht_stack, list_stack);
|
||||
abort = abort
|
||||
|| set_ref_in_item(&HI2DI(hi)->di_tv, copyID,
|
||||
&ht_stack, list_stack, tuple_stack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,7 +375,7 @@ set_ref_in_dict(dict_T *d, int copyID)
|
||||
if (d != NULL && d->dv_copyID != copyID)
|
||||
{
|
||||
d->dv_copyID = copyID;
|
||||
return set_ref_in_ht(&d->dv_hashtab, copyID, NULL);
|
||||
return set_ref_in_ht(&d->dv_hashtab, copyID, NULL, NULL);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -382,7 +391,7 @@ set_ref_in_list(list_T *ll, int copyID)
|
||||
if (ll != NULL && ll->lv_copyID != copyID)
|
||||
{
|
||||
ll->lv_copyID = copyID;
|
||||
return set_ref_in_list_items(ll, copyID, NULL);
|
||||
return set_ref_in_list_items(ll, copyID, NULL, NULL);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -394,7 +403,11 @@ set_ref_in_list(list_T *ll, int copyID)
|
||||
* Returns TRUE if setting references failed somehow.
|
||||
*/
|
||||
int
|
||||
set_ref_in_list_items(list_T *l, int copyID, ht_stack_T **ht_stack)
|
||||
set_ref_in_list_items(
|
||||
list_T *l,
|
||||
int copyID,
|
||||
ht_stack_T **ht_stack,
|
||||
tuple_stack_T **tuple_stack)
|
||||
{
|
||||
listitem_T *li;
|
||||
int abort = FALSE;
|
||||
@@ -411,7 +424,7 @@ set_ref_in_list_items(list_T *l, int copyID, ht_stack_T **ht_stack)
|
||||
// list_stack.
|
||||
for (li = cur_l->lv_first; !abort && li != NULL; li = li->li_next)
|
||||
abort = abort || set_ref_in_item(&li->li_tv, copyID,
|
||||
ht_stack, &list_stack);
|
||||
ht_stack, &list_stack, tuple_stack);
|
||||
if (list_stack == NULL)
|
||||
break;
|
||||
|
||||
@@ -425,6 +438,50 @@ set_ref_in_list_items(list_T *l, int copyID, ht_stack_T **ht_stack)
|
||||
return abort;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark all lists and dicts referenced through tuple "t" with "copyID".
|
||||
* "ht_stack" is used to add hashtabs to be marked. Can be NULL.
|
||||
*
|
||||
* Returns TRUE if setting references failed somehow.
|
||||
*/
|
||||
int
|
||||
set_ref_in_tuple_items(
|
||||
tuple_T *tuple,
|
||||
int copyID,
|
||||
ht_stack_T **ht_stack,
|
||||
list_stack_T **list_stack)
|
||||
{
|
||||
int abort = FALSE;
|
||||
tuple_T *cur_t;
|
||||
tuple_stack_T *tuple_stack = NULL;
|
||||
tuple_stack_T *tempitem;
|
||||
|
||||
cur_t = tuple;
|
||||
for (;;)
|
||||
{
|
||||
// Mark each item in the tuple. If the item contains a hashtab
|
||||
// it is added to ht_stack, if it contains a list it is added to
|
||||
// list_stack.
|
||||
for (int i = 0; i < cur_t->tv_items.ga_len; i++)
|
||||
{
|
||||
typval_T *tv = ((typval_T *)cur_t->tv_items.ga_data) + i;
|
||||
abort = abort
|
||||
|| set_ref_in_item(tv, copyID,
|
||||
ht_stack, list_stack, &tuple_stack);
|
||||
}
|
||||
if (tuple_stack == NULL)
|
||||
break;
|
||||
|
||||
// take an item from the stack
|
||||
cur_t = tuple_stack->tuple;
|
||||
tempitem = tuple_stack;
|
||||
tuple_stack = tuple_stack->prev;
|
||||
free(tempitem);
|
||||
}
|
||||
|
||||
return abort;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the partial in callback 'cb' with "copyID".
|
||||
*/
|
||||
@@ -438,7 +495,7 @@ set_ref_in_callback(callback_T *cb, int copyID)
|
||||
|
||||
tv.v_type = VAR_PARTIAL;
|
||||
tv.vval.v_partial = cb->cb_partial;
|
||||
return set_ref_in_item(&tv, copyID, NULL, NULL);
|
||||
return set_ref_in_item(&tv, copyID, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -450,7 +507,8 @@ set_ref_in_item_dict(
|
||||
dict_T *dd,
|
||||
int copyID,
|
||||
ht_stack_T **ht_stack,
|
||||
list_stack_T **list_stack)
|
||||
list_stack_T **list_stack,
|
||||
tuple_stack_T **tuple_stack)
|
||||
{
|
||||
if (dd == NULL || dd->dv_copyID == copyID)
|
||||
return FALSE;
|
||||
@@ -458,7 +516,7 @@ set_ref_in_item_dict(
|
||||
// Didn't see this dict yet.
|
||||
dd->dv_copyID = copyID;
|
||||
if (ht_stack == NULL)
|
||||
return set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
|
||||
return set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack, tuple_stack);
|
||||
|
||||
ht_stack_T *newitem = ALLOC_ONE(ht_stack_T);
|
||||
if (newitem == NULL)
|
||||
@@ -480,7 +538,8 @@ set_ref_in_item_list(
|
||||
list_T *ll,
|
||||
int copyID,
|
||||
ht_stack_T **ht_stack,
|
||||
list_stack_T **list_stack)
|
||||
list_stack_T **list_stack,
|
||||
tuple_stack_T **tuple_stack)
|
||||
{
|
||||
if (ll == NULL || ll->lv_copyID == copyID)
|
||||
return FALSE;
|
||||
@@ -488,7 +547,7 @@ set_ref_in_item_list(
|
||||
// Didn't see this list yet.
|
||||
ll->lv_copyID = copyID;
|
||||
if (list_stack == NULL)
|
||||
return set_ref_in_list_items(ll, copyID, ht_stack);
|
||||
return set_ref_in_list_items(ll, copyID, ht_stack, tuple_stack);
|
||||
|
||||
list_stack_T *newitem = ALLOC_ONE(list_stack_T);
|
||||
if (newitem == NULL)
|
||||
@@ -501,6 +560,37 @@ set_ref_in_item_list(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the tuple "tt" with "copyID".
|
||||
* Also see set_ref_in_item().
|
||||
*/
|
||||
static int
|
||||
set_ref_in_item_tuple(
|
||||
tuple_T *tt,
|
||||
int copyID,
|
||||
ht_stack_T **ht_stack,
|
||||
list_stack_T **list_stack,
|
||||
tuple_stack_T **tuple_stack)
|
||||
{
|
||||
if (tt == NULL || tt->tv_copyID == copyID)
|
||||
return FALSE;
|
||||
|
||||
// Didn't see this tuple yet.
|
||||
tt->tv_copyID = copyID;
|
||||
if (tuple_stack == NULL)
|
||||
return set_ref_in_tuple_items(tt, copyID, ht_stack, list_stack);
|
||||
|
||||
tuple_stack_T *newitem = ALLOC_ONE(tuple_stack_T);
|
||||
if (newitem == NULL)
|
||||
return TRUE;
|
||||
|
||||
newitem->tuple = tt;
|
||||
newitem->prev = *tuple_stack;
|
||||
*tuple_stack = newitem;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the partial "pt" with "copyID".
|
||||
* Also see set_ref_in_item().
|
||||
@@ -510,7 +600,8 @@ set_ref_in_item_partial(
|
||||
partial_T *pt,
|
||||
int copyID,
|
||||
ht_stack_T **ht_stack,
|
||||
list_stack_T **list_stack)
|
||||
list_stack_T **list_stack,
|
||||
tuple_stack_T **tuple_stack)
|
||||
{
|
||||
if (pt == NULL || pt->pt_copyID == copyID)
|
||||
return FALSE;
|
||||
@@ -526,7 +617,7 @@ set_ref_in_item_partial(
|
||||
|
||||
dtv.v_type = VAR_DICT;
|
||||
dtv.vval.v_dict = pt->pt_dict;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack, tuple_stack);
|
||||
}
|
||||
|
||||
if (pt->pt_obj != NULL)
|
||||
@@ -535,12 +626,12 @@ set_ref_in_item_partial(
|
||||
|
||||
objtv.v_type = VAR_OBJECT;
|
||||
objtv.vval.v_object = pt->pt_obj;
|
||||
set_ref_in_item(&objtv, copyID, ht_stack, list_stack);
|
||||
set_ref_in_item(&objtv, copyID, ht_stack, list_stack, tuple_stack);
|
||||
}
|
||||
|
||||
for (int i = 0; i < pt->pt_argc; ++i)
|
||||
abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID,
|
||||
ht_stack, list_stack);
|
||||
ht_stack, list_stack, tuple_stack);
|
||||
// pt_funcstack is handled in set_ref_in_funcstacks()
|
||||
// pt_loopvars is handled in set_ref_in_loopvars()
|
||||
|
||||
@@ -557,7 +648,8 @@ set_ref_in_item_job(
|
||||
job_T *job,
|
||||
int copyID,
|
||||
ht_stack_T **ht_stack,
|
||||
list_stack_T **list_stack)
|
||||
list_stack_T **list_stack,
|
||||
tuple_stack_T **tuple_stack)
|
||||
{
|
||||
typval_T dtv;
|
||||
|
||||
@@ -569,13 +661,13 @@ set_ref_in_item_job(
|
||||
{
|
||||
dtv.v_type = VAR_CHANNEL;
|
||||
dtv.vval.v_channel = job->jv_channel;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack, tuple_stack);
|
||||
}
|
||||
if (job->jv_exit_cb.cb_partial != NULL)
|
||||
{
|
||||
dtv.v_type = VAR_PARTIAL;
|
||||
dtv.vval.v_partial = job->jv_exit_cb.cb_partial;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack, tuple_stack);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -590,7 +682,8 @@ set_ref_in_item_channel(
|
||||
channel_T *ch,
|
||||
int copyID,
|
||||
ht_stack_T **ht_stack,
|
||||
list_stack_T **list_stack)
|
||||
list_stack_T **list_stack,
|
||||
tuple_stack_T **tuple_stack)
|
||||
{
|
||||
typval_T dtv;
|
||||
|
||||
@@ -602,33 +695,33 @@ set_ref_in_item_channel(
|
||||
{
|
||||
for (jsonq_T *jq = ch->ch_part[part].ch_json_head.jq_next;
|
||||
jq != NULL; jq = jq->jq_next)
|
||||
set_ref_in_item(jq->jq_value, copyID, ht_stack, list_stack);
|
||||
set_ref_in_item(jq->jq_value, copyID, ht_stack, list_stack, tuple_stack);
|
||||
for (cbq_T *cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL;
|
||||
cq = cq->cq_next)
|
||||
if (cq->cq_callback.cb_partial != NULL)
|
||||
{
|
||||
dtv.v_type = VAR_PARTIAL;
|
||||
dtv.vval.v_partial = cq->cq_callback.cb_partial;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack, tuple_stack);
|
||||
}
|
||||
if (ch->ch_part[part].ch_callback.cb_partial != NULL)
|
||||
{
|
||||
dtv.v_type = VAR_PARTIAL;
|
||||
dtv.vval.v_partial = ch->ch_part[part].ch_callback.cb_partial;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack, tuple_stack);
|
||||
}
|
||||
}
|
||||
if (ch->ch_callback.cb_partial != NULL)
|
||||
{
|
||||
dtv.v_type = VAR_PARTIAL;
|
||||
dtv.vval.v_partial = ch->ch_callback.cb_partial;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack, tuple_stack);
|
||||
}
|
||||
if (ch->ch_close_cb.cb_partial != NULL)
|
||||
{
|
||||
dtv.v_type = VAR_PARTIAL;
|
||||
dtv.vval.v_partial = ch->ch_close_cb.cb_partial;
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
|
||||
set_ref_in_item(&dtv, copyID, ht_stack, list_stack, tuple_stack);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -644,7 +737,8 @@ set_ref_in_item_class(
|
||||
class_T *cl,
|
||||
int copyID,
|
||||
ht_stack_T **ht_stack,
|
||||
list_stack_T **list_stack)
|
||||
list_stack_T **list_stack,
|
||||
tuple_stack_T **tuple_stack)
|
||||
{
|
||||
int abort = FALSE;
|
||||
|
||||
@@ -659,7 +753,7 @@ set_ref_in_item_class(
|
||||
for (int i = 0; !abort && i < cl->class_class_member_count; ++i)
|
||||
abort = abort || set_ref_in_item(
|
||||
&cl->class_members_tv[i],
|
||||
copyID, ht_stack, list_stack);
|
||||
copyID, ht_stack, list_stack, tuple_stack);
|
||||
}
|
||||
|
||||
for (int i = 0; !abort && i < cl->class_class_function_count; ++i)
|
||||
@@ -682,7 +776,8 @@ set_ref_in_item_object(
|
||||
object_T *obj,
|
||||
int copyID,
|
||||
ht_stack_T **ht_stack,
|
||||
list_stack_T **list_stack)
|
||||
list_stack_T **list_stack,
|
||||
tuple_stack_T **tuple_stack)
|
||||
{
|
||||
int abort = FALSE;
|
||||
|
||||
@@ -696,7 +791,7 @@ set_ref_in_item_object(
|
||||
for (int i = 0; !abort
|
||||
&& i < obj->obj_class->class_obj_member_count; ++i)
|
||||
abort = abort || set_ref_in_item(mtv + i, copyID,
|
||||
ht_stack, list_stack);
|
||||
ht_stack, list_stack, tuple_stack);
|
||||
|
||||
return abort;
|
||||
}
|
||||
@@ -714,7 +809,8 @@ set_ref_in_item(
|
||||
typval_T *tv,
|
||||
int copyID,
|
||||
ht_stack_T **ht_stack,
|
||||
list_stack_T **list_stack)
|
||||
list_stack_T **list_stack,
|
||||
tuple_stack_T **tuple_stack)
|
||||
{
|
||||
int abort = FALSE;
|
||||
|
||||
@@ -722,12 +818,15 @@ set_ref_in_item(
|
||||
{
|
||||
case VAR_DICT:
|
||||
return set_ref_in_item_dict(tv->vval.v_dict, copyID,
|
||||
ht_stack, list_stack);
|
||||
ht_stack, list_stack, tuple_stack);
|
||||
|
||||
case VAR_LIST:
|
||||
return set_ref_in_item_list(tv->vval.v_list, copyID,
|
||||
ht_stack, list_stack);
|
||||
ht_stack, list_stack, tuple_stack);
|
||||
|
||||
case VAR_TUPLE:
|
||||
return set_ref_in_item_tuple(tv->vval.v_tuple, copyID,
|
||||
ht_stack, list_stack, tuple_stack);
|
||||
case VAR_FUNC:
|
||||
{
|
||||
abort = set_ref_in_func(tv->vval.v_string, NULL, copyID);
|
||||
@@ -736,12 +835,12 @@ set_ref_in_item(
|
||||
|
||||
case VAR_PARTIAL:
|
||||
return set_ref_in_item_partial(tv->vval.v_partial, copyID,
|
||||
ht_stack, list_stack);
|
||||
ht_stack, list_stack, tuple_stack);
|
||||
|
||||
case VAR_JOB:
|
||||
#ifdef FEAT_JOB_CHANNEL
|
||||
return set_ref_in_item_job(tv->vval.v_job, copyID,
|
||||
ht_stack, list_stack);
|
||||
ht_stack, list_stack, tuple_stack);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
@@ -749,18 +848,18 @@ set_ref_in_item(
|
||||
case VAR_CHANNEL:
|
||||
#ifdef FEAT_JOB_CHANNEL
|
||||
return set_ref_in_item_channel(tv->vval.v_channel, copyID,
|
||||
ht_stack, list_stack);
|
||||
ht_stack, list_stack, tuple_stack);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
|
||||
case VAR_CLASS:
|
||||
return set_ref_in_item_class(tv->vval.v_class, copyID,
|
||||
ht_stack, list_stack);
|
||||
ht_stack, list_stack, tuple_stack);
|
||||
|
||||
case VAR_OBJECT:
|
||||
return set_ref_in_item_object(tv->vval.v_object, copyID,
|
||||
ht_stack, list_stack);
|
||||
ht_stack, list_stack, tuple_stack);
|
||||
|
||||
case VAR_UNKNOWN:
|
||||
case VAR_ANY:
|
||||
|
Reference in New Issue
Block a user