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 {