0
0
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:
Yegappan Lakshmanan
2025-03-23 16:42:16 +01:00
committed by Christian Brabandt
parent adb703e1b9
commit 9cb865e95b
75 changed files with 7155 additions and 691 deletions

185
src/gc.c
View File

@@ -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: