comparison src/ex_eval.c @ 22551:86a115a80262 v8.2.1824

patch 8.2.1824: Vim9: variables at the script level escape their scope Commit: https://github.com/vim/vim/commit/fcdc5d83fbfd7ddce634769ea902e58c87f27f20 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Oct 10 19:07:09 2020 +0200 patch 8.2.1824: Vim9: variables at the script level escape their scope Problem: Vim9: variables at the script level escape their scope. Solution: When leaving a scope remove variables declared in it.
author Bram Moolenaar <Bram@vim.org>
date Sat, 10 Oct 2020 19:15:04 +0200
parents a607f02fd17a
children 3ed3bed38e0f
comparison
equal deleted inserted replaced
22550:d61c22faf4be 22551:86a115a80262
904 904
905 clear_evalarg(&evalarg, eap); 905 clear_evalarg(&evalarg, eap);
906 } 906 }
907 907
908 /* 908 /*
909 * Start a new scope/block. Caller should have checked that cs_idx is not
910 * exceeding CSTACK_LEN.
911 */
912 static void
913 enter_block(cstack_T *cstack)
914 {
915 ++cstack->cs_idx;
916 if (in_vim9script())
917 cstack->cs_script_var_len[cstack->cs_idx] =
918 SCRIPT_ITEM(current_sctx.sc_sid)->sn_var_vals.ga_len;
919 }
920
921 static void
922 leave_block(cstack_T *cstack)
923 {
924 int i;
925
926 if (in_vim9script())
927 {
928 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
929
930 for (i = cstack->cs_script_var_len[cstack->cs_idx];
931 i < si->sn_var_vals.ga_len; ++i)
932 {
933 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + i;
934 hashtab_T *ht = get_script_local_ht();
935 hashitem_T *hi;
936
937 if (ht != NULL)
938 {
939 // Remove a variable declared inside the block, if it still
940 // exists.
941 hi = hash_find(ht, sv->sv_name);
942 if (!HASHITEM_EMPTY(hi))
943 delete_var(ht, hi);
944 }
945 }
946 }
947 --cstack->cs_idx;
948 }
949
950 /*
909 * ":if". 951 * ":if".
910 */ 952 */
911 void 953 void
912 ex_if(exarg_T *eap) 954 ex_if(exarg_T *eap)
913 { 955 {
918 960
919 if (cstack->cs_idx == CSTACK_LEN - 1) 961 if (cstack->cs_idx == CSTACK_LEN - 1)
920 eap->errmsg = _("E579: :if nesting too deep"); 962 eap->errmsg = _("E579: :if nesting too deep");
921 else 963 else
922 { 964 {
923 ++cstack->cs_idx; 965 enter_block(cstack);
924 cstack->cs_flags[cstack->cs_idx] = 0; 966 cstack->cs_flags[cstack->cs_idx] = 0;
925 967
926 /* 968 /*
927 * Don't do something after an error, interrupt, or throw, or when there 969 * Don't do something after an error, interrupt, or throw, or when
928 * is a surrounding conditional and it was not active. 970 * there is a surrounding conditional and it was not active.
929 */ 971 */
930 skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0 972 skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0
931 && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)); 973 && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
932 974
933 result = eval_to_bool(eap->arg, &error, eap, skip); 975 result = eval_to_bool(eap->arg, &error, eap, skip);
947 * ":endif". 989 * ":endif".
948 */ 990 */
949 void 991 void
950 ex_endif(exarg_T *eap) 992 ex_endif(exarg_T *eap)
951 { 993 {
994 cstack_T *cstack = eap->cstack;
995
952 did_endif = TRUE; 996 did_endif = TRUE;
953 if (eap->cstack->cs_idx < 0 997 if (cstack->cs_idx < 0
954 || (eap->cstack->cs_flags[eap->cstack->cs_idx] 998 || (cstack->cs_flags[cstack->cs_idx]
955 & (CSF_WHILE | CSF_FOR | CSF_TRY))) 999 & (CSF_WHILE | CSF_FOR | CSF_TRY)))
956 eap->errmsg = _(e_endif_without_if); 1000 eap->errmsg = _(e_endif_without_if);
957 else 1001 else
958 { 1002 {
959 /* 1003 /*
963 * Handle a ">quit" debug command as if an interrupt had occurred before 1007 * Handle a ">quit" debug command as if an interrupt had occurred before
964 * the ":endif". That is, throw an interrupt exception if appropriate. 1008 * the ":endif". That is, throw an interrupt exception if appropriate.
965 * Doing this here prevents an exception for a parsing error being 1009 * Doing this here prevents an exception for a parsing error being
966 * discarded by throwing the interrupt exception later on. 1010 * discarded by throwing the interrupt exception later on.
967 */ 1011 */
968 if (!(eap->cstack->cs_flags[eap->cstack->cs_idx] & CSF_TRUE) 1012 if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE)
969 && dbg_check_skipped(eap)) 1013 && dbg_check_skipped(eap))
970 (void)do_intthrow(eap->cstack); 1014 (void)do_intthrow(cstack);
971 1015
972 --eap->cstack->cs_idx; 1016 leave_block(cstack);
973 } 1017 }
974 } 1018 }
975 1019
976 /* 1020 /*
977 * ":else" and ":elseif". 1021 * ":else" and ":elseif".
1084 * ":endwhile" or ":endfor". When not set, need to initialise this 1128 * ":endwhile" or ":endfor". When not set, need to initialise this
1085 * cstack entry. 1129 * cstack entry.
1086 */ 1130 */
1087 if ((cstack->cs_lflags & CSL_HAD_LOOP) == 0) 1131 if ((cstack->cs_lflags & CSL_HAD_LOOP) == 0)
1088 { 1132 {
1089 ++cstack->cs_idx; 1133 enter_block(cstack);
1090 ++cstack->cs_looplevel; 1134 ++cstack->cs_looplevel;
1091 cstack->cs_line[cstack->cs_idx] = -1; 1135 cstack->cs_line[cstack->cs_idx] = -1;
1092 } 1136 }
1093 cstack->cs_flags[cstack->cs_idx] = 1137 cstack->cs_flags[cstack->cs_idx] =
1094 eap->cmdidx == CMD_while ? CSF_WHILE : CSF_FOR; 1138 eap->cmdidx == CMD_while ? CSF_WHILE : CSF_FOR;
1448 1492
1449 if (cstack->cs_idx == CSTACK_LEN - 1) 1493 if (cstack->cs_idx == CSTACK_LEN - 1)
1450 eap->errmsg = _("E601: :try nesting too deep"); 1494 eap->errmsg = _("E601: :try nesting too deep");
1451 else 1495 else
1452 { 1496 {
1453 ++cstack->cs_idx; 1497 enter_block(cstack);
1454 ++cstack->cs_trylevel; 1498 ++cstack->cs_trylevel;
1455 cstack->cs_flags[cstack->cs_idx] = CSF_TRY; 1499 cstack->cs_flags[cstack->cs_idx] = CSF_TRY;
1456 cstack->cs_pending[cstack->cs_idx] = CSTP_NONE; 1500 cstack->cs_pending[cstack->cs_idx] = CSTP_NONE;
1457 1501
1458 /* 1502 /*
1921 * after errors except when this ":endtry" is not within a ":try". 1965 * after errors except when this ":endtry" is not within a ":try".
1922 * Restore "emsg_silent" if it has been reset by this try conditional. 1966 * Restore "emsg_silent" if it has been reset by this try conditional.
1923 */ 1967 */
1924 (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE); 1968 (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE);
1925 1969
1926 --cstack->cs_idx; 1970 leave_block(cstack);
1927 --cstack->cs_trylevel; 1971 --cstack->cs_trylevel;
1928 1972
1929 if (!skip) 1973 if (!skip)
1930 { 1974 {
1931 report_resume_pending(pending, 1975 report_resume_pending(pending,
2301 { 2345 {
2302 if (cstack->cs_flags[cstack->cs_idx] & cond_type) 2346 if (cstack->cs_flags[cstack->cs_idx] & cond_type)
2303 --*cond_level; 2347 --*cond_level;
2304 if (cstack->cs_flags[cstack->cs_idx] & CSF_FOR) 2348 if (cstack->cs_flags[cstack->cs_idx] & CSF_FOR)
2305 free_for_info(cstack->cs_forinfo[cstack->cs_idx]); 2349 free_for_info(cstack->cs_forinfo[cstack->cs_idx]);
2306 --cstack->cs_idx; 2350 leave_block(cstack);
2307 } 2351 }
2308 } 2352 }
2309 2353
2310 /* 2354 /*
2311 * ":endfunction" when not after a ":function" 2355 * ":endfunction" when not after a ":function"