Mercurial > vim
comparison src/vim9execute.c @ 25800:fe8d153cb268 v8.2.3435
patch 8.2.3435: Vim9: dict is not passed to dict function
Commit: https://github.com/vim/vim/commit/b1b6f4de2b0edc3b6622912132ddb8994ec52709
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Sep 13 18:25:54 2021 +0200
patch 8.2.3435: Vim9: dict is not passed to dict function
Problem: Vim9: dict is not passed to dict function.
Solution: Keep the dict used until a function call.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 13 Sep 2021 18:30:04 +0200 |
parents | f31cf0388eab |
children | dd4e86558836 |
comparison
equal
deleted
inserted
replaced
25799:0493410eba74 | 25800:fe8d153cb268 |
---|---|
161 | 161 |
162 ufunc->uf_debug_tick = debug_tick; | 162 ufunc->uf_debug_tick = debug_tick; |
163 breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name, 0); | 163 breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name, 0); |
164 ufunc->uf_has_breakpoint = breakpoint > 0; | 164 ufunc->uf_has_breakpoint = breakpoint > 0; |
165 } | 165 } |
166 } | |
167 | |
168 static garray_T dict_stack = GA_EMPTY; | |
169 | |
170 /* | |
171 * Put a value on the dict stack. This consumes "tv". | |
172 */ | |
173 static int | |
174 dict_stack_save(typval_T *tv) | |
175 { | |
176 if (dict_stack.ga_growsize == 0) | |
177 ga_init2(&dict_stack, (int)sizeof(typval_T), 10); | |
178 if (ga_grow(&dict_stack, 1) == FAIL) | |
179 return FAIL; | |
180 ((typval_T *)dict_stack.ga_data)[dict_stack.ga_len] = *tv; | |
181 ++dict_stack.ga_len; | |
182 return OK; | |
183 } | |
184 | |
185 /* | |
186 * Get the typval at top of the dict stack. | |
187 */ | |
188 static typval_T * | |
189 dict_stack_get_tv(void) | |
190 { | |
191 if (dict_stack.ga_len == 0) | |
192 return NULL; | |
193 return ((typval_T *)dict_stack.ga_data) + dict_stack.ga_len - 1; | |
194 } | |
195 | |
196 /* | |
197 * Get the dict at top of the dict stack. | |
198 */ | |
199 static dict_T * | |
200 dict_stack_get_dict(void) | |
201 { | |
202 typval_T *tv; | |
203 | |
204 if (dict_stack.ga_len == 0) | |
205 return NULL; | |
206 tv = ((typval_T *)dict_stack.ga_data) + dict_stack.ga_len - 1; | |
207 if (tv->v_type == VAR_DICT) | |
208 return tv->vval.v_dict; | |
209 return NULL; | |
210 } | |
211 | |
212 /* | |
213 * Drop an item from the dict stack. | |
214 */ | |
215 static void | |
216 dict_stack_drop(void) | |
217 { | |
218 if (dict_stack.ga_len == 0) | |
219 { | |
220 iemsg("Dict stack underflow"); | |
221 return; | |
222 } | |
223 --dict_stack.ga_len; | |
224 clear_tv(((typval_T *)dict_stack.ga_data) + dict_stack.ga_len); | |
225 } | |
226 | |
227 /* | |
228 * Drop items from the dict stack until the length is equal to "len". | |
229 */ | |
230 static void | |
231 dict_stack_clear(int len) | |
232 { | |
233 while (dict_stack.ga_len > len) | |
234 dict_stack_drop(); | |
166 } | 235 } |
167 | 236 |
168 /* | 237 /* |
169 * Call compiled function "cdf_idx" from compiled code. | 238 * Call compiled function "cdf_idx" from compiled code. |
170 * This adds a stack frame and sets the instruction pointer to the start of the | 239 * This adds a stack frame and sets the instruction pointer to the start of the |
763 call_ufunc( | 832 call_ufunc( |
764 ufunc_T *ufunc, | 833 ufunc_T *ufunc, |
765 partial_T *pt, | 834 partial_T *pt, |
766 int argcount, | 835 int argcount, |
767 ectx_T *ectx, | 836 ectx_T *ectx, |
768 isn_T *iptr) | 837 isn_T *iptr, |
838 dict_T *selfdict) | |
769 { | 839 { |
770 typval_T argvars[MAX_FUNC_ARGS]; | 840 typval_T argvars[MAX_FUNC_ARGS]; |
771 funcexe_T funcexe; | 841 funcexe_T funcexe; |
772 int error; | 842 int error; |
773 int idx; | 843 int idx; |
805 | 875 |
806 if (call_prepare(argcount, argvars, ectx) == FAIL) | 876 if (call_prepare(argcount, argvars, ectx) == FAIL) |
807 return FAIL; | 877 return FAIL; |
808 CLEAR_FIELD(funcexe); | 878 CLEAR_FIELD(funcexe); |
809 funcexe.evaluate = TRUE; | 879 funcexe.evaluate = TRUE; |
880 funcexe.selfdict = selfdict != NULL ? selfdict : dict_stack_get_dict(); | |
810 | 881 |
811 // Call the user function. Result goes in last position on the stack. | 882 // Call the user function. Result goes in last position on the stack. |
812 // TODO: add selfdict if there is one | 883 // TODO: add selfdict if there is one |
813 error = call_user_func_check(ufunc, argcount, argvars, | 884 error = call_user_func_check(ufunc, argcount, argvars, |
814 STACK_TV_BOT(-1), &funcexe, NULL); | 885 STACK_TV_BOT(-1), &funcexe, funcexe.selfdict); |
815 | 886 |
816 // Clear the arguments. | 887 // Clear the arguments. |
817 for (idx = 0; idx < argcount; ++idx) | 888 for (idx = 0; idx < argcount; ++idx) |
818 clear_tv(&argvars[idx]); | 889 clear_tv(&argvars[idx]); |
819 | 890 |
862 static int | 933 static int |
863 call_by_name( | 934 call_by_name( |
864 char_u *name, | 935 char_u *name, |
865 int argcount, | 936 int argcount, |
866 ectx_T *ectx, | 937 ectx_T *ectx, |
867 isn_T *iptr) | 938 isn_T *iptr, |
939 dict_T *selfdict) | |
868 { | 940 { |
869 ufunc_T *ufunc; | 941 ufunc_T *ufunc; |
870 | 942 |
871 if (builtin_function(name, -1)) | 943 if (builtin_function(name, -1)) |
872 { | 944 { |
914 &argv[i], NULL, i + 1) == FAIL) | 986 &argv[i], NULL, i + 1) == FAIL) |
915 return FAIL; | 987 return FAIL; |
916 } | 988 } |
917 } | 989 } |
918 | 990 |
919 return call_ufunc(ufunc, NULL, argcount, ectx, iptr); | 991 return call_ufunc(ufunc, NULL, argcount, ectx, iptr, selfdict); |
920 } | 992 } |
921 | 993 |
922 return FAIL; | 994 return FAIL; |
923 } | 995 } |
924 | 996 |
930 { | 1002 { |
931 int argcount = argcount_arg; | 1003 int argcount = argcount_arg; |
932 char_u *name = NULL; | 1004 char_u *name = NULL; |
933 int called_emsg_before = called_emsg; | 1005 int called_emsg_before = called_emsg; |
934 int res = FAIL; | 1006 int res = FAIL; |
1007 dict_T *selfdict = NULL; | |
935 | 1008 |
936 if (tv->v_type == VAR_PARTIAL) | 1009 if (tv->v_type == VAR_PARTIAL) |
937 { | 1010 { |
938 partial_T *pt = tv->vval.v_partial; | 1011 partial_T *pt = tv->vval.v_partial; |
939 int i; | 1012 int i; |
951 | 1024 |
952 // copy the arguments from the partial onto the stack | 1025 // copy the arguments from the partial onto the stack |
953 for (i = 0; i < pt->pt_argc; ++i) | 1026 for (i = 0; i < pt->pt_argc; ++i) |
954 copy_tv(&pt->pt_argv[i], STACK_TV_BOT(-argcount + i)); | 1027 copy_tv(&pt->pt_argv[i], STACK_TV_BOT(-argcount + i)); |
955 } | 1028 } |
1029 selfdict = pt->pt_dict; | |
956 | 1030 |
957 if (pt->pt_func != NULL) | 1031 if (pt->pt_func != NULL) |
958 return call_ufunc(pt->pt_func, pt, argcount, ectx, NULL); | 1032 return call_ufunc(pt->pt_func, pt, argcount, ectx, NULL, selfdict); |
959 | 1033 |
960 name = pt->pt_name; | 1034 name = pt->pt_name; |
961 } | 1035 } |
962 else if (tv->v_type == VAR_FUNC) | 1036 else if (tv->v_type == VAR_FUNC) |
963 name = tv->vval.v_string; | 1037 name = tv->vval.v_string; |
971 // May need to translate <SNR>123_ to K_SNR. | 1045 // May need to translate <SNR>123_ to K_SNR. |
972 fname = fname_trans_sid(name, fname_buf, &tofree, &error); | 1046 fname = fname_trans_sid(name, fname_buf, &tofree, &error); |
973 if (error != FCERR_NONE) | 1047 if (error != FCERR_NONE) |
974 res = FAIL; | 1048 res = FAIL; |
975 else | 1049 else |
976 res = call_by_name(fname, argcount, ectx, NULL); | 1050 res = call_by_name(fname, argcount, ectx, NULL, selfdict); |
977 vim_free(tofree); | 1051 vim_free(tofree); |
978 } | 1052 } |
979 | 1053 |
980 if (res == FAIL) | 1054 if (res == FAIL) |
981 { | 1055 { |
1323 isn_T *iptr) | 1397 isn_T *iptr) |
1324 { | 1398 { |
1325 int called_emsg_before = called_emsg; | 1399 int called_emsg_before = called_emsg; |
1326 int res; | 1400 int res; |
1327 | 1401 |
1328 res = call_by_name(name, argcount, ectx, iptr); | 1402 res = call_by_name(name, argcount, ectx, iptr, NULL); |
1329 if (res == FAIL && called_emsg == called_emsg_before) | 1403 if (res == FAIL && called_emsg == called_emsg_before) |
1330 { | 1404 { |
1331 dictitem_T *v; | 1405 dictitem_T *v; |
1332 | 1406 |
1333 v = find_var(name, NULL, FALSE); | 1407 v = find_var(name, NULL, FALSE); |
1568 static int | 1642 static int |
1569 exec_instructions(ectx_T *ectx) | 1643 exec_instructions(ectx_T *ectx) |
1570 { | 1644 { |
1571 int ret = FAIL; | 1645 int ret = FAIL; |
1572 int save_trylevel_at_start = ectx->ec_trylevel_at_start; | 1646 int save_trylevel_at_start = ectx->ec_trylevel_at_start; |
1647 int dict_stack_len_at_start = dict_stack.ga_len; | |
1573 | 1648 |
1574 // Start execution at the first instruction. | 1649 // Start execution at the first instruction. |
1575 ectx->ec_iidx = 0; | 1650 ectx->ec_iidx = 0; |
1576 | 1651 |
1577 // Only catch exceptions in this instruction list. | 1652 // Only catch exceptions in this instruction list. |
4020 case ISN_MEMBER: | 4095 case ISN_MEMBER: |
4021 { | 4096 { |
4022 dict_T *dict; | 4097 dict_T *dict; |
4023 char_u *key; | 4098 char_u *key; |
4024 dictitem_T *di; | 4099 dictitem_T *di; |
4025 typval_T temp_tv; | |
4026 | 4100 |
4027 // dict member: dict is at stack-2, key at stack-1 | 4101 // dict member: dict is at stack-2, key at stack-1 |
4028 tv = STACK_TV_BOT(-2); | 4102 tv = STACK_TV_BOT(-2); |
4029 // no need to check for VAR_DICT, CHECKTYPE will check. | 4103 // no need to check for VAR_DICT, CHECKTYPE will check. |
4030 dict = tv->vval.v_dict; | 4104 dict = tv->vval.v_dict; |
4039 { | 4113 { |
4040 SOURCING_LNUM = iptr->isn_lnum; | 4114 SOURCING_LNUM = iptr->isn_lnum; |
4041 semsg(_(e_dictkey), key); | 4115 semsg(_(e_dictkey), key); |
4042 | 4116 |
4043 // If :silent! is used we will continue, make sure the | 4117 // If :silent! is used we will continue, make sure the |
4044 // stack contents makes sense. | 4118 // stack contents makes sense and the dict stack is |
4119 // updated. | |
4045 clear_tv(tv); | 4120 clear_tv(tv); |
4046 --ectx->ec_stack.ga_len; | 4121 --ectx->ec_stack.ga_len; |
4047 tv = STACK_TV_BOT(-1); | 4122 tv = STACK_TV_BOT(-1); |
4048 clear_tv(tv); | 4123 (void) dict_stack_save(tv); |
4049 tv->v_type = VAR_NUMBER; | 4124 tv->v_type = VAR_NUMBER; |
4050 tv->vval.v_number = 0; | 4125 tv->vval.v_number = 0; |
4051 goto on_fatal_error; | 4126 goto on_fatal_error; |
4052 } | 4127 } |
4053 clear_tv(tv); | 4128 clear_tv(tv); |
4054 --ectx->ec_stack.ga_len; | 4129 --ectx->ec_stack.ga_len; |
4055 // Clear the dict only after getting the item, to avoid | 4130 // Put the dict used on the dict stack, it might be used by |
4056 // that it makes the item invalid. | 4131 // a dict function later. |
4057 tv = STACK_TV_BOT(-1); | 4132 tv = STACK_TV_BOT(-1); |
4058 temp_tv = *tv; | 4133 if (dict_stack_save(tv) == FAIL) |
4134 goto on_fatal_error; | |
4059 copy_tv(&di->di_tv, tv); | 4135 copy_tv(&di->di_tv, tv); |
4060 clear_tv(&temp_tv); | |
4061 } | 4136 } |
4062 break; | 4137 break; |
4063 | 4138 |
4064 // dict member with string key | 4139 // dict member with string key |
4065 case ISN_STRINGMEMBER: | 4140 case ISN_STRINGMEMBER: |
4066 { | 4141 { |
4067 dict_T *dict; | 4142 dict_T *dict; |
4068 dictitem_T *di; | 4143 dictitem_T *di; |
4069 typval_T temp_tv; | |
4070 | 4144 |
4071 tv = STACK_TV_BOT(-1); | 4145 tv = STACK_TV_BOT(-1); |
4072 if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL) | 4146 if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL) |
4073 { | 4147 { |
4074 SOURCING_LNUM = iptr->isn_lnum; | 4148 SOURCING_LNUM = iptr->isn_lnum; |
4082 { | 4156 { |
4083 SOURCING_LNUM = iptr->isn_lnum; | 4157 SOURCING_LNUM = iptr->isn_lnum; |
4084 semsg(_(e_dictkey), iptr->isn_arg.string); | 4158 semsg(_(e_dictkey), iptr->isn_arg.string); |
4085 goto on_error; | 4159 goto on_error; |
4086 } | 4160 } |
4087 // Clear the dict after getting the item, to avoid that it | 4161 // Put the dict used on the dict stack, it might be used by |
4088 // make the item invalid. | 4162 // a dict function later. |
4089 temp_tv = *tv; | 4163 if (dict_stack_save(tv) == FAIL) |
4164 goto on_fatal_error; | |
4165 | |
4090 copy_tv(&di->di_tv, tv); | 4166 copy_tv(&di->di_tv, tv); |
4091 clear_tv(&temp_tv); | 4167 } |
4168 break; | |
4169 | |
4170 case ISN_CLEARDICT: | |
4171 dict_stack_drop(); | |
4172 break; | |
4173 | |
4174 case ISN_USEDICT: | |
4175 { | |
4176 typval_T *dict_tv = dict_stack_get_tv(); | |
4177 | |
4178 // Turn "dict.Func" into a partial for "Func" bound to | |
4179 // "dict". Don't do this when "Func" is already a partial | |
4180 // that was bound explicitly (pt_auto is FALSE). | |
4181 tv = STACK_TV_BOT(-1); | |
4182 if (dict_tv != NULL | |
4183 && dict_tv->v_type == VAR_DICT | |
4184 && dict_tv->vval.v_dict != NULL | |
4185 && (tv->v_type == VAR_FUNC | |
4186 || (tv->v_type == VAR_PARTIAL | |
4187 && (tv->vval.v_partial->pt_auto | |
4188 || tv->vval.v_partial->pt_dict == NULL)))) | |
4189 dict_tv->vval.v_dict = | |
4190 make_partial(dict_tv->vval.v_dict, tv); | |
4191 dict_stack_drop(); | |
4092 } | 4192 } |
4093 break; | 4193 break; |
4094 | 4194 |
4095 case ISN_NEGATENR: | 4195 case ISN_NEGATENR: |
4096 tv = STACK_TV_BOT(-1); | 4196 tv = STACK_TV_BOT(-1); |
4476 } | 4576 } |
4477 | 4577 |
4478 done: | 4578 done: |
4479 ret = OK; | 4579 ret = OK; |
4480 theend: | 4580 theend: |
4581 dict_stack_clear(dict_stack_len_at_start); | |
4481 ectx->ec_trylevel_at_start = save_trylevel_at_start; | 4582 ectx->ec_trylevel_at_start = save_trylevel_at_start; |
4482 return ret; | 4583 return ret; |
4483 } | 4584 } |
4484 | 4585 |
4485 /* | 4586 /* |
5566 iptr->isn_arg.getitem.gi_with_op ? | 5667 iptr->isn_arg.getitem.gi_with_op ? |
5567 " with op" : ""); break; | 5668 " with op" : ""); break; |
5568 case ISN_MEMBER: smsg("%s%4d MEMBER", pfx, current); break; | 5669 case ISN_MEMBER: smsg("%s%4d MEMBER", pfx, current); break; |
5569 case ISN_STRINGMEMBER: smsg("%s%4d MEMBER %s", pfx, current, | 5670 case ISN_STRINGMEMBER: smsg("%s%4d MEMBER %s", pfx, current, |
5570 iptr->isn_arg.string); break; | 5671 iptr->isn_arg.string); break; |
5672 case ISN_CLEARDICT: smsg("%s%4d CLEARDICT", pfx, current); break; | |
5673 case ISN_USEDICT: smsg("%s%4d USEDICT", pfx, current); break; | |
5674 | |
5571 case ISN_NEGATENR: smsg("%s%4d NEGATENR", pfx, current); break; | 5675 case ISN_NEGATENR: smsg("%s%4d NEGATENR", pfx, current); break; |
5572 | 5676 |
5573 case ISN_CHECKNR: smsg("%s%4d CHECKNR", pfx, current); break; | 5677 case ISN_CHECKNR: smsg("%s%4d CHECKNR", pfx, current); break; |
5574 case ISN_CHECKTYPE: | 5678 case ISN_CHECKTYPE: |
5575 { | 5679 { |