comparison src/eval.c @ 31686:966f1213dd35 v9.0.1175

patch 9.0.1175: the set_ref_in_item() function is too long Commit: https://github.com/vim/vim/commit/ea125393af01ecaf75cee8e085a57f8143f3ae3e Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Wed Jan 11 11:46:17 2023 +0000 patch 9.0.1175: the set_ref_in_item() function is too long Problem: The set_ref_in_item() function is too long. Solution: Use a separate function for more complicated types. (Yegappan Lakshmanan, closes #11802)
author Bram Moolenaar <Bram@vim.org>
date Wed, 11 Jan 2023 13:00:05 +0100
parents 62237ea155d9
children 57248cc8bd70
comparison
equal deleted inserted replaced
31685:2ed7c3993447 31686:966f1213dd35
5482 tv.vval.v_partial = cb->cb_partial; 5482 tv.vval.v_partial = cb->cb_partial;
5483 return set_ref_in_item(&tv, copyID, NULL, NULL); 5483 return set_ref_in_item(&tv, copyID, NULL, NULL);
5484 } 5484 }
5485 5485
5486 /* 5486 /*
5487 * Mark the dict "dd" with "copyID".
5488 * Also see set_ref_in_item().
5489 */
5490 static int
5491 set_ref_in_item_dict(
5492 dict_T *dd,
5493 int copyID,
5494 ht_stack_T **ht_stack,
5495 list_stack_T **list_stack)
5496 {
5497 if (dd == NULL || dd->dv_copyID == copyID)
5498 return FALSE;
5499
5500 // Didn't see this dict yet.
5501 dd->dv_copyID = copyID;
5502 if (ht_stack == NULL)
5503 return set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
5504
5505 ht_stack_T *newitem = ALLOC_ONE(ht_stack_T);
5506 if (newitem == NULL)
5507 return TRUE;
5508
5509 newitem->ht = &dd->dv_hashtab;
5510 newitem->prev = *ht_stack;
5511 *ht_stack = newitem;
5512
5513 return FALSE;
5514 }
5515
5516 /*
5517 * Mark the list "ll" with "copyID".
5518 * Also see set_ref_in_item().
5519 */
5520 static int
5521 set_ref_in_item_list(
5522 list_T *ll,
5523 int copyID,
5524 ht_stack_T **ht_stack,
5525 list_stack_T **list_stack)
5526 {
5527 if (ll == NULL || ll->lv_copyID == copyID)
5528 return FALSE;
5529
5530 // Didn't see this list yet.
5531 ll->lv_copyID = copyID;
5532 if (list_stack == NULL)
5533 return set_ref_in_list_items(ll, copyID, ht_stack);
5534
5535 list_stack_T *newitem = ALLOC_ONE(list_stack_T);
5536 if (newitem == NULL)
5537 return TRUE;
5538
5539 newitem->list = ll;
5540 newitem->prev = *list_stack;
5541 *list_stack = newitem;
5542
5543 return FALSE;
5544 }
5545
5546 /*
5547 * Mark the partial "pt" with "copyID".
5548 * Also see set_ref_in_item().
5549 */
5550 static int
5551 set_ref_in_item_partial(
5552 partial_T *pt,
5553 int copyID,
5554 ht_stack_T **ht_stack,
5555 list_stack_T **list_stack)
5556 {
5557 if (pt == NULL || pt->pt_copyID == copyID)
5558 return FALSE;
5559
5560 // Didn't see this partial yet.
5561 pt->pt_copyID = copyID;
5562
5563 int abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID);
5564
5565 if (pt->pt_dict != NULL)
5566 {
5567 typval_T dtv;
5568
5569 dtv.v_type = VAR_DICT;
5570 dtv.vval.v_dict = pt->pt_dict;
5571 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5572 }
5573
5574 for (int i = 0; i < pt->pt_argc; ++i)
5575 abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID,
5576 ht_stack, list_stack);
5577 // pt_funcstack is handled in set_ref_in_funcstacks()
5578 // pt_loopvars is handled in set_ref_in_loopvars()
5579
5580 return abort;
5581 }
5582
5583 /*
5584 * Mark the job "pt" with "copyID".
5585 * Also see set_ref_in_item().
5586 */
5587 static int
5588 set_ref_in_item_job(
5589 job_T *job,
5590 int copyID,
5591 ht_stack_T **ht_stack,
5592 list_stack_T **list_stack)
5593 {
5594 #ifdef FEAT_JOB_CHANNEL
5595 typval_T dtv;
5596
5597 if (job == NULL || job->jv_copyID == copyID)
5598 return FALSE;
5599
5600 job->jv_copyID = copyID;
5601 if (job->jv_channel != NULL)
5602 {
5603 dtv.v_type = VAR_CHANNEL;
5604 dtv.vval.v_channel = job->jv_channel;
5605 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5606 }
5607 if (job->jv_exit_cb.cb_partial != NULL)
5608 {
5609 dtv.v_type = VAR_PARTIAL;
5610 dtv.vval.v_partial = job->jv_exit_cb.cb_partial;
5611 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5612 }
5613 #endif
5614
5615 return FALSE;
5616 }
5617
5618 /*
5619 * Mark the channel "ch" with "copyID".
5620 * Also see set_ref_in_item().
5621 */
5622 static int
5623 set_ref_in_item_channel(
5624 channel_T *ch,
5625 int copyID,
5626 ht_stack_T **ht_stack,
5627 list_stack_T **list_stack)
5628 {
5629 #ifdef FEAT_JOB_CHANNEL
5630 typval_T dtv;
5631
5632 if (ch == NULL || ch->ch_copyID == copyID)
5633 return FALSE;
5634
5635 ch->ch_copyID = copyID;
5636 for (ch_part_T part = PART_SOCK; part < PART_COUNT; ++part)
5637 {
5638 for (jsonq_T *jq = ch->ch_part[part].ch_json_head.jq_next;
5639 jq != NULL; jq = jq->jq_next)
5640 set_ref_in_item(jq->jq_value, copyID, ht_stack, list_stack);
5641 for (cbq_T *cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL;
5642 cq = cq->cq_next)
5643 if (cq->cq_callback.cb_partial != NULL)
5644 {
5645 dtv.v_type = VAR_PARTIAL;
5646 dtv.vval.v_partial = cq->cq_callback.cb_partial;
5647 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5648 }
5649 if (ch->ch_part[part].ch_callback.cb_partial != NULL)
5650 {
5651 dtv.v_type = VAR_PARTIAL;
5652 dtv.vval.v_partial = ch->ch_part[part].ch_callback.cb_partial;
5653 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5654 }
5655 }
5656 if (ch->ch_callback.cb_partial != NULL)
5657 {
5658 dtv.v_type = VAR_PARTIAL;
5659 dtv.vval.v_partial = ch->ch_callback.cb_partial;
5660 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5661 }
5662 if (ch->ch_close_cb.cb_partial != NULL)
5663 {
5664 dtv.v_type = VAR_PARTIAL;
5665 dtv.vval.v_partial = ch->ch_close_cb.cb_partial;
5666 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5667 }
5668 #endif
5669
5670 return FALSE;
5671 }
5672
5673 /*
5674 * Mark the class "cl" with "copyID".
5675 * Also see set_ref_in_item().
5676 */
5677 static int
5678 set_ref_in_item_class(
5679 class_T *cl,
5680 int copyID,
5681 ht_stack_T **ht_stack,
5682 list_stack_T **list_stack)
5683 {
5684 int abort = FALSE;
5685
5686 if (cl == NULL || cl->class_copyID == copyID
5687 || (cl->class_flags & CLASS_INTERFACE) != 0)
5688 return FALSE;
5689
5690 cl->class_copyID = copyID;
5691 for (int i = 0; !abort && i < cl->class_class_member_count; ++i)
5692 abort = abort || set_ref_in_item(
5693 &cl->class_members_tv[i],
5694 copyID, ht_stack, list_stack);
5695
5696 for (int i = 0; !abort && i < cl->class_class_function_count; ++i)
5697 abort = abort || set_ref_in_func(NULL,
5698 cl->class_class_functions[i], copyID);
5699
5700 for (int i = 0; !abort && i < cl->class_obj_method_count; ++i)
5701 abort = abort || set_ref_in_func(NULL,
5702 cl->class_obj_methods[i], copyID);
5703
5704 return abort;
5705 }
5706
5707 /*
5708 * Mark the object "cl" with "copyID".
5709 * Also see set_ref_in_item().
5710 */
5711 static int
5712 set_ref_in_item_object(
5713 object_T *obj,
5714 int copyID,
5715 ht_stack_T **ht_stack,
5716 list_stack_T **list_stack)
5717 {
5718 int abort = FALSE;
5719
5720 if (obj == NULL || obj->obj_copyID == copyID)
5721 return FALSE;
5722
5723 obj->obj_copyID = copyID;
5724
5725 // The typval_T array is right after the object_T.
5726 typval_T *mtv = (typval_T *)(obj + 1);
5727 for (int i = 0; !abort
5728 && i < obj->obj_class->class_obj_member_count; ++i)
5729 abort = abort || set_ref_in_item(mtv + i, copyID,
5730 ht_stack, list_stack);
5731
5732 return abort;
5733 }
5734
5735 /*
5487 * Mark all lists, dicts and other container types referenced through typval 5736 * Mark all lists, dicts and other container types referenced through typval
5488 * "tv" with "copyID". 5737 * "tv" with "copyID".
5489 * "list_stack" is used to add lists to be marked. Can be NULL. 5738 * "list_stack" is used to add lists to be marked. Can be NULL.
5490 * "ht_stack" is used to add hashtabs to be marked. Can be NULL. 5739 * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
5491 * 5740 *
5501 int abort = FALSE; 5750 int abort = FALSE;
5502 5751
5503 switch (tv->v_type) 5752 switch (tv->v_type)
5504 { 5753 {
5505 case VAR_DICT: 5754 case VAR_DICT:
5506 { 5755 return set_ref_in_item_dict(tv->vval.v_dict, copyID,
5507 dict_T *dd = tv->vval.v_dict; 5756 ht_stack, list_stack);
5508
5509 if (dd != NULL && dd->dv_copyID != copyID)
5510 {
5511 // Didn't see this dict yet.
5512 dd->dv_copyID = copyID;
5513 if (ht_stack == NULL)
5514 {
5515 abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
5516 }
5517 else
5518 {
5519 ht_stack_T *newitem = ALLOC_ONE(ht_stack_T);
5520
5521 if (newitem == NULL)
5522 abort = TRUE;
5523 else
5524 {
5525 newitem->ht = &dd->dv_hashtab;
5526 newitem->prev = *ht_stack;
5527 *ht_stack = newitem;
5528 }
5529 }
5530 }
5531 break;
5532 }
5533 5757
5534 case VAR_LIST: 5758 case VAR_LIST:
5535 { 5759 return set_ref_in_item_list(tv->vval.v_list, copyID,
5536 list_T *ll = tv->vval.v_list; 5760 ht_stack, list_stack);
5537
5538 if (ll != NULL && ll->lv_copyID != copyID)
5539 {
5540 // Didn't see this list yet.
5541 ll->lv_copyID = copyID;
5542 if (list_stack == NULL)
5543 {
5544 abort = set_ref_in_list_items(ll, copyID, ht_stack);
5545 }
5546 else
5547 {
5548 list_stack_T *newitem = ALLOC_ONE(list_stack_T);
5549
5550 if (newitem == NULL)
5551 abort = TRUE;
5552 else
5553 {
5554 newitem->list = ll;
5555 newitem->prev = *list_stack;
5556 *list_stack = newitem;
5557 }
5558 }
5559 }
5560 break;
5561 }
5562 5761
5563 case VAR_FUNC: 5762 case VAR_FUNC:
5564 { 5763 {
5565 abort = set_ref_in_func(tv->vval.v_string, NULL, copyID); 5764 abort = set_ref_in_func(tv->vval.v_string, NULL, copyID);
5566 break; 5765 break;
5567 } 5766 }
5568 5767
5569 case VAR_PARTIAL: 5768 case VAR_PARTIAL:
5570 { 5769 return set_ref_in_item_partial(tv->vval.v_partial, copyID,
5571 partial_T *pt = tv->vval.v_partial; 5770 ht_stack, list_stack);
5572 int i; 5771
5573 5772 case VAR_JOB:
5574 if (pt != NULL && pt->pt_copyID != copyID) 5773 return set_ref_in_item_job(tv->vval.v_job, copyID,
5575 {
5576 // Didn't see this partial yet.
5577 pt->pt_copyID = copyID;
5578
5579 abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID);
5580
5581 if (pt->pt_dict != NULL)
5582 {
5583 typval_T dtv;
5584
5585 dtv.v_type = VAR_DICT;
5586 dtv.vval.v_dict = pt->pt_dict;
5587 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5588 }
5589
5590 for (i = 0; i < pt->pt_argc; ++i)
5591 abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID,
5592 ht_stack, list_stack); 5774 ht_stack, list_stack);
5593 // pt_funcstack is handled in set_ref_in_funcstacks()
5594 // pt_loopvars is handled in set_ref_in_loopvars()
5595 }
5596 break;
5597 }
5598
5599 case VAR_JOB:
5600 {
5601 #ifdef FEAT_JOB_CHANNEL
5602 job_T *job = tv->vval.v_job;
5603 typval_T dtv;
5604
5605 if (job != NULL && job->jv_copyID != copyID)
5606 {
5607 job->jv_copyID = copyID;
5608 if (job->jv_channel != NULL)
5609 {
5610 dtv.v_type = VAR_CHANNEL;
5611 dtv.vval.v_channel = job->jv_channel;
5612 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5613 }
5614 if (job->jv_exit_cb.cb_partial != NULL)
5615 {
5616 dtv.v_type = VAR_PARTIAL;
5617 dtv.vval.v_partial = job->jv_exit_cb.cb_partial;
5618 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5619 }
5620 }
5621 #endif
5622 break;
5623 }
5624 5775
5625 case VAR_CHANNEL: 5776 case VAR_CHANNEL:
5626 { 5777 return set_ref_in_item_channel(tv->vval.v_channel, copyID,
5627 #ifdef FEAT_JOB_CHANNEL
5628 channel_T *ch = tv->vval.v_channel;
5629 ch_part_T part;
5630 typval_T dtv;
5631 jsonq_T *jq;
5632 cbq_T *cq;
5633
5634 if (ch != NULL && ch->ch_copyID != copyID)
5635 {
5636 ch->ch_copyID = copyID;
5637 for (part = PART_SOCK; part < PART_COUNT; ++part)
5638 {
5639 for (jq = ch->ch_part[part].ch_json_head.jq_next;
5640 jq != NULL; jq = jq->jq_next)
5641 set_ref_in_item(jq->jq_value, copyID,
5642 ht_stack, list_stack); 5778 ht_stack, list_stack);
5643 for (cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL;
5644 cq = cq->cq_next)
5645 if (cq->cq_callback.cb_partial != NULL)
5646 {
5647 dtv.v_type = VAR_PARTIAL;
5648 dtv.vval.v_partial = cq->cq_callback.cb_partial;
5649 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5650 }
5651 if (ch->ch_part[part].ch_callback.cb_partial != NULL)
5652 {
5653 dtv.v_type = VAR_PARTIAL;
5654 dtv.vval.v_partial =
5655 ch->ch_part[part].ch_callback.cb_partial;
5656 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5657 }
5658 }
5659 if (ch->ch_callback.cb_partial != NULL)
5660 {
5661 dtv.v_type = VAR_PARTIAL;
5662 dtv.vval.v_partial = ch->ch_callback.cb_partial;
5663 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5664 }
5665 if (ch->ch_close_cb.cb_partial != NULL)
5666 {
5667 dtv.v_type = VAR_PARTIAL;
5668 dtv.vval.v_partial = ch->ch_close_cb.cb_partial;
5669 set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
5670 }
5671 }
5672 #endif
5673 break;
5674 }
5675 5779
5676 case VAR_CLASS: 5780 case VAR_CLASS:
5677 { 5781 return set_ref_in_item_class(tv->vval.v_class, copyID,
5678 class_T *cl = tv->vval.v_class; 5782 ht_stack, list_stack);
5679 if (cl != NULL && cl->class_copyID != copyID
5680 && (cl->class_flags && CLASS_INTERFACE) == 0)
5681 {
5682 cl->class_copyID = copyID;
5683 for (int i = 0; !abort
5684 && i < cl->class_class_member_count; ++i)
5685 abort = abort || set_ref_in_item(
5686 &cl->class_members_tv[i],
5687 copyID, ht_stack, list_stack);
5688
5689
5690 for (int i = 0; !abort
5691 && i < cl->class_class_function_count; ++i)
5692 abort = abort || set_ref_in_func(NULL,
5693 cl->class_class_functions[i], copyID);
5694
5695 for (int i = 0; !abort
5696 && i < cl->class_obj_method_count; ++i)
5697 abort = abort || set_ref_in_func(NULL,
5698 cl->class_obj_methods[i], copyID);
5699
5700 // Mark initializer expressions?
5701 }
5702 break;
5703 }
5704 5783
5705 case VAR_OBJECT: 5784 case VAR_OBJECT:
5706 { 5785 return set_ref_in_item_object(tv->vval.v_object, copyID,
5707 object_T *obj = tv->vval.v_object;
5708 if (obj != NULL && obj->obj_copyID != copyID)
5709 {
5710 obj->obj_copyID = copyID;
5711
5712 // The typval_T array is right after the object_T.
5713 typval_T *mtv = (typval_T *)(obj + 1);
5714 for (int i = 0; !abort
5715 && i < obj->obj_class->class_obj_member_count; ++i)
5716 abort = abort || set_ref_in_item(mtv + i, copyID,
5717 ht_stack, list_stack); 5786 ht_stack, list_stack);
5718 }
5719 break;
5720 }
5721 5787
5722 case VAR_UNKNOWN: 5788 case VAR_UNKNOWN:
5723 case VAR_ANY: 5789 case VAR_ANY:
5724 case VAR_VOID: 5790 case VAR_VOID:
5725 case VAR_BOOL: 5791 case VAR_BOOL: