comparison src/vim9script.c @ 22594:209c7aa56325 v8.2.1845

patch 8.2.1845: Vim9: function defined in a block can't use block variables Commit: https://github.com/vim/vim/commit/8d739de43b84ef7817b3b5b826d1cbfe7572a62a Author: Bram Moolenaar <Bram@vim.org> Date: Wed Oct 14 19:39:19 2020 +0200 patch 8.2.1845: Vim9: function defined in a block can't use block variables Problem: Vim9: function defined in a block can't use variables defined in that block. Solution: First step: Make a second hashtab that holds all script variables, also block-local ones, with more information.
author Bram Moolenaar <Bram@vim.org>
date Wed, 14 Oct 2020 19:45:04 +0200
parents 35ef9b0a81a3
children 107eae953b87
comparison
equal deleted inserted replaced
22593:a6030e19b08f 22594:209c7aa56325
132 132
133 /* 133 /*
134 * Free all imported items in script "sid". 134 * Free all imported items in script "sid".
135 */ 135 */
136 void 136 void
137 free_imports(int sid) 137 free_imports_and_script_vars(int sid)
138 { 138 {
139 scriptitem_T *si = SCRIPT_ITEM(sid); 139 scriptitem_T *si = SCRIPT_ITEM(sid);
140 int idx; 140 int idx;
141 141
142 for (idx = 0; idx < si->sn_imports.ga_len; ++idx) 142 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
144 imported_T *imp = ((imported_T *)si->sn_imports.ga_data) + idx; 144 imported_T *imp = ((imported_T *)si->sn_imports.ga_data) + idx;
145 145
146 vim_free(imp->imp_name); 146 vim_free(imp->imp_name);
147 } 147 }
148 ga_clear(&si->sn_imports); 148 ga_clear(&si->sn_imports);
149 ga_clear(&si->sn_var_vals); 149
150 free_all_script_vars(si);
151
150 clear_type_list(&si->sn_type_list); 152 clear_type_list(&si->sn_type_list);
151 } 153 }
152 154
153 /* 155 /*
154 * ":import Item from 'filename'" 156 * ":import Item from 'filename'"
563 vim_free(name); 565 vim_free(name);
564 return p; 566 return p;
565 } 567 }
566 568
567 /* 569 /*
570 * Vim9 part of adding a script variable: add it to sn_all_vars and
571 * sn_var_vals.
572 * When "type" is NULL use "tv" for the type.
573 */
574 void
575 add_vim9_script_var(dictitem_T *di, typval_T *tv, type_T *type)
576 {
577 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
578
579 // Store a pointer to the typval_T, so that it can be found by
580 // index instead of using a hastab lookup.
581 if (ga_grow(&si->sn_var_vals, 1) == OK)
582 {
583 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
584 + si->sn_var_vals.ga_len;
585 hashitem_T *hi;
586 sallvar_T *newsav = (sallvar_T *)alloc_clear(
587 sizeof(sallvar_T) + STRLEN(di->di_key));
588
589 if (newsav == NULL)
590 return;
591
592 sv->sv_tv = &di->di_tv;
593 if (type == NULL)
594 sv->sv_type = typval2type(tv, &si->sn_type_list);
595 else
596 sv->sv_type = type;
597 sv->sv_const = (di->di_flags & DI_FLAGS_LOCK) ? ASSIGN_CONST : 0;
598 sv->sv_export = is_export;
599 newsav->sav_var_vals_idx = si->sn_var_vals.ga_len;
600 ++si->sn_var_vals.ga_len;
601
602 STRCPY(&newsav->sav_key, di->di_key);
603 sv->sv_name = newsav->sav_key;
604 newsav->sav_di = di;
605 newsav->sav_block_id = si->sn_current_block_id;
606
607 hi = hash_find(&si->sn_all_vars.dv_hashtab, newsav->sav_key);
608 if (!HASHITEM_EMPTY(hi))
609 {
610 sallvar_T *sav = HI2SAV(hi);
611
612 // variable with this name exists in another block
613 while (sav->sav_next != NULL)
614 sav = sav->sav_next;
615 sav->sav_next = newsav;
616 }
617 else
618 // new variable name
619 hash_add(&si->sn_all_vars.dv_hashtab, newsav->sav_key);
620
621 // let ex_export() know the export worked.
622 is_export = FALSE;
623 }
624 }
625
626 void
627 hide_script_var(scriptitem_T *si, svar_T *sv)
628 {
629 hashtab_T *script_ht = get_script_local_ht();
630 hashtab_T *all_ht = &si->sn_all_vars.dv_hashtab;
631 hashitem_T *script_hi;
632 hashitem_T *all_hi;
633
634 // Remove a variable declared inside the block, if it still exists.
635 // The typval is moved into the sallvar_T.
636 script_hi = hash_find(script_ht, sv->sv_name);
637 all_hi = hash_find(all_ht, sv->sv_name);
638 if (!HASHITEM_EMPTY(script_hi) && !HASHITEM_EMPTY(all_hi))
639 {
640 dictitem_T *di = HI2DI(script_hi);
641 sallvar_T *sav = HI2SAV(all_hi);
642
643 sav->sav_tv = di->di_tv;
644 di->di_tv.v_type = VAR_UNKNOWN;
645 sav->sav_flags = di->di_flags;
646 sav->sav_di = NULL;
647 delete_var(script_ht, script_hi);
648 }
649 }
650
651 /*
652 * Free the script variables from "sn_all_vars".
653 */
654 void
655 free_all_script_vars(scriptitem_T *si)
656 {
657 int todo;
658 hashtab_T *ht = &si->sn_all_vars.dv_hashtab;
659 hashitem_T *hi;
660 sallvar_T *sav;
661 sallvar_T *sav_next;
662
663 hash_lock(ht);
664 todo = (int)ht->ht_used;
665 for (hi = ht->ht_array; todo > 0; ++hi)
666 {
667 if (!HASHITEM_EMPTY(hi))
668 {
669 --todo;
670
671 // Free the variable. Don't remove it from the hashtab, ht_array
672 // might change then. hash_clear() takes care of it later.
673 sav = HI2SAV(hi);
674 while (sav != NULL)
675 {
676 sav_next = sav->sav_next;
677 if (sav->sav_di == NULL)
678 clear_tv(&sav->sav_tv);
679 vim_free(sav);
680 sav = sav_next;
681 }
682 }
683 }
684 hash_clear(ht);
685 hash_init(ht);
686
687 ga_clear(&si->sn_var_vals);
688 }
689
690 /*
568 * Find the script-local variable that links to "dest". 691 * Find the script-local variable that links to "dest".
569 * Returns NULL if not found. 692 * Returns NULL if not found.
570 */ 693 */
571 svar_T * 694 svar_T *
572 find_typval_in_script(typval_T *dest) 695 find_typval_in_script(typval_T *dest)