comparison src/vim9execute.c @ 19328:e99e6d794597 v8.2.0222

patch 8.2.0222: Vim9: optional function arguments don't work yet Commit: https://github.com/vim/vim/commit/170fcfcf250954d76fca86e3fed088ddfdb49383 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Feb 6 17:51:35 2020 +0100 patch 8.2.0222: Vim9: optional function arguments don't work yet Problem: Vim9: optional function arguments don't work yet. Solution: Implement optional function arguments.
author Bram Moolenaar <Bram@vim.org>
date Thu, 06 Feb 2020 18:00:04 +0100
parents 17dc6282f370
children 61646c189622
comparison
equal deleted inserted replaced
19327:6bbb4ad91d21 19328:e99e6d794597
68 68
69 // Get pointer to item relative to the bottom of the stack, -1 is the last one. 69 // Get pointer to item relative to the bottom of the stack, -1 is the last one.
70 #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + idx) 70 #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + idx)
71 71
72 /* 72 /*
73 * Return the number of arguments, including any vararg. 73 * Return the number of arguments, including optional arguments and any vararg.
74 */ 74 */
75 static int 75 static int
76 ufunc_argcount(ufunc_T *ufunc) 76 ufunc_argcount(ufunc_T *ufunc)
77 { 77 {
78 return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0); 78 return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0);
79 }
80
81 /*
82 * Set the instruction index, depending on omitted arguments, where the default
83 * values are to be computed. If all optional arguments are present, start
84 * with the function body.
85 * The expression evaluation is at the start of the instructions:
86 * 0 -> EVAL default1
87 * STORE arg[-2]
88 * 1 -> EVAL default2
89 * STORE arg[-1]
90 * 2 -> function body
91 */
92 static void
93 init_instr_idx(ufunc_T *ufunc, int argcount, ectx_T *ectx)
94 {
95 if (ufunc->uf_def_args.ga_len == 0)
96 ectx->ec_iidx = 0;
97 else
98 {
99 int defcount = ufunc->uf_args.ga_len - argcount;
100
101 // If there is a varargs argument defcount can be negative, no defaults
102 // to evaluate then.
103 if (defcount < 0)
104 defcount = 0;
105 ectx->ec_iidx = ufunc->uf_def_arg_idx[
106 ufunc->uf_def_args.ga_len - defcount];
107 }
79 } 108 }
80 109
81 /* 110 /*
82 * Call compiled function "cdf_idx" from compiled code. 111 * Call compiled function "cdf_idx" from compiled code.
83 * 112 *
105 } 134 }
106 135
107 if (ga_grow(&ectx->ec_stack, optcount + 3 + dfunc->df_varcount) == FAIL) 136 if (ga_grow(&ectx->ec_stack, optcount + 3 + dfunc->df_varcount) == FAIL)
108 return FAIL; 137 return FAIL;
109 138
110 // TODO: Put omitted argument default values on the stack.
111 if (optcount > 0)
112 {
113 emsg("optional arguments not implemented yet");
114 return FAIL;
115 }
116 if (optcount < 0) 139 if (optcount < 0)
117 { 140 {
118 emsg("argument count wrong?"); 141 emsg("argument count wrong?");
119 return FAIL; 142 return FAIL;
120 } 143 }
121 // for (idx = argcount - dfunc->df_minarg; 144
122 // idx < dfunc->df_maxarg; ++idx) 145 // Reserve space for omitted optional arguments, filled in soon.
123 // { 146 // Also any empty varargs argument.
124 // copy_tv(&dfunc->df_defarg[idx], STACK_TV_BOT(0)); 147 ectx->ec_stack.ga_len += optcount;
125 // ++ectx->ec_stack.ga_len;
126 // }
127 148
128 // Store current execution state in stack frame for ISN_RETURN. 149 // Store current execution state in stack frame for ISN_RETURN.
129 // TODO: If the actual number of arguments doesn't match what the called 150 // TODO: If the actual number of arguments doesn't match what the called
130 // function expects things go bad. 151 // function expects things go bad.
131 STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx; 152 STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx;
140 161
141 // Set execution state to the start of the called function. 162 // Set execution state to the start of the called function.
142 ectx->ec_dfunc_idx = cdf_idx; 163 ectx->ec_dfunc_idx = cdf_idx;
143 ectx->ec_instr = dfunc->df_instr; 164 ectx->ec_instr = dfunc->df_instr;
144 estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1); 165 estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1);
145 ectx->ec_iidx = 0; 166
167 // Decide where to start execution, handles optional arguments.
168 init_instr_idx(ufunc, argcount, ectx);
146 169
147 return OK; 170 return OK;
148 } 171 }
149 172
150 // Get pointer to item in the stack. 173 // Get pointer to item in the stack.
154 * Return from the current function. 177 * Return from the current function.
155 */ 178 */
156 static void 179 static void
157 func_return(ectx_T *ectx) 180 func_return(ectx_T *ectx)
158 { 181 {
159 int ret_idx = ectx->ec_stack.ga_len - 1;
160 int idx; 182 int idx;
161 dfunc_T *dfunc; 183 dfunc_T *dfunc;
184 int top;
162 185
163 // execution context goes one level up 186 // execution context goes one level up
164 estack_pop(); 187 estack_pop();
165 188
166 // Clear the local variables and temporary values, but not 189 // Clear the local variables and temporary values, but not
167 // the return value. 190 // the return value.
168 for (idx = ectx->ec_frame + STACK_FRAME_SIZE; 191 for (idx = ectx->ec_frame + STACK_FRAME_SIZE;
169 idx < ectx->ec_stack.ga_len - 1; ++idx) 192 idx < ectx->ec_stack.ga_len - 1; ++idx)
170 clear_tv(STACK_TV(idx)); 193 clear_tv(STACK_TV(idx));
194
195 // Clear the arguments.
171 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; 196 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
172 ectx->ec_stack.ga_len = ectx->ec_frame 197 top = ectx->ec_frame - ufunc_argcount(dfunc->df_ufunc);
173 - ufunc_argcount(dfunc->df_ufunc) + 1; 198 for (idx = top; idx < ectx->ec_frame; ++idx)
199 clear_tv(STACK_TV(idx));
200
201 // Restore the previous frame.
174 ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame)->vval.v_number; 202 ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame)->vval.v_number;
175 ectx->ec_iidx = STACK_TV(ectx->ec_frame + 1)->vval.v_number; 203 ectx->ec_iidx = STACK_TV(ectx->ec_frame + 1)->vval.v_number;
176 ectx->ec_frame = STACK_TV(ectx->ec_frame + 2)->vval.v_number; 204 ectx->ec_frame = STACK_TV(ectx->ec_frame + 2)->vval.v_number;
177 *STACK_TV_BOT(-1) = *STACK_TV(ret_idx);
178 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; 205 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
179 ectx->ec_instr = dfunc->df_instr; 206 ectx->ec_instr = dfunc->df_instr;
207
208 // Reset the stack to the position before the call, move the return value
209 // to the top of the stack.
210 idx = ectx->ec_stack.ga_len - 1;
211 ectx->ec_stack.ga_len = top + 1;
212 *STACK_TV_BOT(-1) = *STACK_TV(idx);
180 } 213 }
181 214
182 #undef STACK_TV 215 #undef STACK_TV
183 216
184 /* 217 /*
360 int initial_frame_ptr; 393 int initial_frame_ptr;
361 typval_T *tv; 394 typval_T *tv;
362 int idx; 395 int idx;
363 int ret = FAIL; 396 int ret = FAIL;
364 dfunc_T *dfunc; 397 dfunc_T *dfunc;
365 int optcount = ufunc_argcount(ufunc) - argc; 398 int defcount = ufunc->uf_args.ga_len - argc;
366 399
367 // Get pointer to item in the stack. 400 // Get pointer to item in the stack.
368 #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) 401 #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
369 402
370 // Get pointer to item at the bottom of the stack, -1 is the bottom. 403 // Get pointer to item at the bottom of the stack, -1 is the bottom.
386 for (idx = 0; idx < argc; ++idx) 419 for (idx = 0; idx < argc; ++idx)
387 { 420 {
388 copy_tv(&argv[idx], STACK_TV_BOT(0)); 421 copy_tv(&argv[idx], STACK_TV_BOT(0));
389 ++ectx.ec_stack.ga_len; 422 ++ectx.ec_stack.ga_len;
390 } 423 }
424 // Make space for omitted arguments, will store default value below.
425 if (defcount > 0)
426 for (idx = 0; idx < defcount; ++idx)
427 {
428 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
429 ++ectx.ec_stack.ga_len;
430 }
391 431
392 // Frame pointer points to just after arguments. 432 // Frame pointer points to just after arguments.
393 ectx.ec_frame = ectx.ec_stack.ga_len; 433 ectx.ec_frame = ectx.ec_stack.ga_len;
394 initial_frame_ptr = ectx.ec_frame; 434 initial_frame_ptr = ectx.ec_frame;
395 435
396 // TODO: Put omitted argument default values on the stack.
397 if (optcount > 0)
398 {
399 emsg("optional arguments not implemented yet");
400 return FAIL;
401 }
402 // dummy frame entries 436 // dummy frame entries
403 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx) 437 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
404 { 438 {
405 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN; 439 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
406 ++ectx.ec_stack.ga_len; 440 ++ectx.ec_stack.ga_len;
411 for (idx = 0; idx < dfunc->df_varcount; ++idx) 445 for (idx = 0; idx < dfunc->df_varcount; ++idx)
412 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; 446 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
413 ectx.ec_stack.ga_len += dfunc->df_varcount; 447 ectx.ec_stack.ga_len += dfunc->df_varcount;
414 448
415 ectx.ec_instr = dfunc->df_instr; 449 ectx.ec_instr = dfunc->df_instr;
416 ectx.ec_iidx = 0; 450
451 // Decide where to start execution, handles optional arguments.
452 init_instr_idx(ufunc, argc, &ectx);
453
417 for (;;) 454 for (;;)
418 { 455 {
419 isn_T *iptr; 456 isn_T *iptr;
420 trycmd_T *trycmd = NULL; 457 trycmd_T *trycmd = NULL;
421 458
1655 case ISN_LOADREG: 1692 case ISN_LOADREG:
1656 smsg("%4d LOADREG @%c", current, iptr->isn_arg.number); 1693 smsg("%4d LOADREG @%c", current, iptr->isn_arg.number);
1657 break; 1694 break;
1658 1695
1659 case ISN_STORE: 1696 case ISN_STORE:
1660 smsg("%4d STORE $%lld", current, iptr->isn_arg.number); 1697 if (iptr->isn_arg.number < 0)
1698 smsg("%4d STORE arg[%lld]", current,
1699 iptr->isn_arg.number + STACK_FRAME_SIZE);
1700 else
1701 smsg("%4d STORE $%lld", current, iptr->isn_arg.number);
1661 break; 1702 break;
1662 case ISN_STOREV: 1703 case ISN_STOREV:
1663 smsg("%4d STOREV v:%s", current, 1704 smsg("%4d STOREV v:%s", current,
1664 get_vim_var_name(iptr->isn_arg.number)); 1705 get_vim_var_name(iptr->isn_arg.number));
1665 break; 1706 break;