comparison src/userfunc.c @ 16615:1a911bd57f11 v8.1.1310

patch 8.1.1310: named function arguments are never optional commit https://github.com/vim/vim/commit/42ae78cfff171fbd7412306083fe200245d7a7a6 Author: Bram Moolenaar <Bram@vim.org> Date: Thu May 9 21:08:58 2019 +0200 patch 8.1.1310: named function arguments are never optional Problem: Named function arguments are never optional. Solution: Support optional function arguments with a default value. (Andy Massimino, closes #3952)
author Bram Moolenaar <Bram@vim.org>
date Thu, 09 May 2019 21:15:05 +0200
parents 7e733046db1d
children a1ba0bd74e7d
comparison
equal deleted inserted replaced
16614:306acde1a598 16615:1a911bd57f11
73 get_function_args( 73 get_function_args(
74 char_u **argp, 74 char_u **argp,
75 char_u endchar, 75 char_u endchar,
76 garray_T *newargs, 76 garray_T *newargs,
77 int *varargs, 77 int *varargs,
78 garray_T *default_args,
78 int skip) 79 int skip)
79 { 80 {
80 int mustend = FALSE; 81 int mustend = FALSE;
81 char_u *arg = *argp; 82 char_u *arg = *argp;
82 char_u *p = arg; 83 char_u *p = arg;
83 int c; 84 int c;
84 int i; 85 int i;
86 int any_default = FALSE;
87 char_u *expr;
85 88
86 if (newargs != NULL) 89 if (newargs != NULL)
87 ga_init2(newargs, (int)sizeof(char_u *), 3); 90 ga_init2(newargs, (int)sizeof(char_u *), 3);
91 if (default_args != NULL)
92 ga_init2(default_args, (int)sizeof(char_u *), 3);
88 93
89 if (varargs != NULL) 94 if (varargs != NULL)
90 *varargs = FALSE; 95 *varargs = FALSE;
91 96
92 /* 97 /*
138 ((char_u **)(newargs->ga_data))[newargs->ga_len] = arg; 143 ((char_u **)(newargs->ga_data))[newargs->ga_len] = arg;
139 newargs->ga_len++; 144 newargs->ga_len++;
140 145
141 *p = c; 146 *p = c;
142 } 147 }
148 if (*skipwhite(p) == '=' && default_args != NULL)
149 {
150 typval_T rettv;
151
152 any_default = TRUE;
153 p = skipwhite(p) + 1;
154 p = skipwhite(p);
155 expr = p;
156 if (eval1(&p, &rettv, FALSE) != FAIL)
157 {
158 if (ga_grow(default_args, 1) == FAIL)
159 goto err_ret;
160
161 // trim trailing whitespace
162 while (p > expr && VIM_ISWHITE(p[-1]))
163 p--;
164 c = *p;
165 *p = NUL;
166 expr = vim_strsave(expr);
167 if (expr == NULL)
168 {
169 *p = c;
170 goto err_ret;
171 }
172 ((char_u **)(default_args->ga_data))
173 [default_args->ga_len] = expr;
174 default_args->ga_len++;
175 *p = c;
176 }
177 else
178 mustend = TRUE;
179 }
180 else if (any_default)
181 {
182 emsg(_("E989: Non-default argument follows default argument"));
183 mustend = TRUE;
184 }
143 if (*p == ',') 185 if (*p == ',')
144 ++p; 186 ++p;
145 else 187 else
146 mustend = TRUE; 188 mustend = TRUE;
147 } 189 }
161 return OK; 203 return OK;
162 204
163 err_ret: 205 err_ret:
164 if (newargs != NULL) 206 if (newargs != NULL)
165 ga_clear_strings(newargs); 207 ga_clear_strings(newargs);
208 if (default_args != NULL)
209 ga_clear_strings(default_args);
166 return FAIL; 210 return FAIL;
167 } 211 }
168 212
169 /* 213 /*
170 * Register function "fp" as using "current_funccal" as its scope. 214 * Register function "fp" as using "current_funccal" as its scope.
208 252
209 ga_init(&newargs); 253 ga_init(&newargs);
210 ga_init(&newlines); 254 ga_init(&newlines);
211 255
212 /* First, check if this is a lambda expression. "->" must exist. */ 256 /* First, check if this is a lambda expression. "->" must exist. */
213 ret = get_function_args(&start, '-', NULL, NULL, TRUE); 257 ret = get_function_args(&start, '-', NULL, NULL, NULL, TRUE);
214 if (ret == FAIL || *start != '>') 258 if (ret == FAIL || *start != '>')
215 return NOTDONE; 259 return NOTDONE;
216 260
217 /* Parse the arguments again. */ 261 /* Parse the arguments again. */
218 if (evaluate) 262 if (evaluate)
219 pnewargs = &newargs; 263 pnewargs = &newargs;
220 else 264 else
221 pnewargs = NULL; 265 pnewargs = NULL;
222 *arg = skipwhite(*arg + 1); 266 *arg = skipwhite(*arg + 1);
223 ret = get_function_args(arg, '-', pnewargs, &varargs, FALSE); 267 ret = get_function_args(arg, '-', pnewargs, &varargs, NULL, FALSE);
224 if (ret == FAIL || **arg != '>') 268 if (ret == FAIL || **arg != '>')
225 goto errret; 269 goto errret;
226 270
227 /* Set up a flag for checking local variables and arguments. */ 271 /* Set up a flag for checking local variables and arguments. */
228 if (evaluate) 272 if (evaluate)
270 314
271 fp->uf_refcount = 1; 315 fp->uf_refcount = 1;
272 STRCPY(fp->uf_name, name); 316 STRCPY(fp->uf_name, name);
273 hash_add(&func_hashtab, UF2HIKEY(fp)); 317 hash_add(&func_hashtab, UF2HIKEY(fp));
274 fp->uf_args = newargs; 318 fp->uf_args = newargs;
319 ga_init(&fp->uf_def_args);
275 fp->uf_lines = newlines; 320 fp->uf_lines = newlines;
276 if (current_funccal != NULL && eval_lavars) 321 if (current_funccal != NULL && eval_lavars)
277 { 322 {
278 flags |= FC_CLOSURE; 323 flags |= FC_CLOSURE;
279 if (register_closure(fp) == FAIL) 324 if (register_closure(fp) == FAIL)
727 linenr_T save_sourcing_lnum; 772 linenr_T save_sourcing_lnum;
728 sctx_T save_current_sctx; 773 sctx_T save_current_sctx;
729 int using_sandbox = FALSE; 774 int using_sandbox = FALSE;
730 funccall_T *fc; 775 funccall_T *fc;
731 int save_did_emsg; 776 int save_did_emsg;
777 int default_arg_err = FALSE;
732 static int depth = 0; 778 static int depth = 0;
733 dictitem_T *v; 779 dictitem_T *v;
734 int fixvar_idx = 0; /* index in fixvar[] */ 780 int fixvar_idx = 0; /* index in fixvar[] */
735 int i; 781 int i;
736 int ai; 782 int ai;
803 ++selfdict->dv_refcount; 849 ++selfdict->dv_refcount;
804 } 850 }
805 851
806 /* 852 /*
807 * Init a: variables. 853 * Init a: variables.
808 * Set a:0 to "argcount". 854 * Set a:0 to "argcount" less number of named arguments, if >= 0.
809 * Set a:000 to a list with room for the "..." arguments. 855 * Set a:000 to a list with room for the "..." arguments.
810 */ 856 */
811 init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE); 857 init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE);
812 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0", 858 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0",
813 (varnumber_T)(argcount - fp->uf_args.ga_len)); 859 (varnumber_T)(argcount >= fp->uf_args.ga_len
860 ? argcount - fp->uf_args.ga_len : 0));
814 fc->l_avars.dv_lock = VAR_FIXED; 861 fc->l_avars.dv_lock = VAR_FIXED;
815 /* Use "name" to avoid a warning from some compiler that checks the 862 /* Use "name" to avoid a warning from some compiler that checks the
816 * destination size. */ 863 * destination size. */
817 v = &fc->fixvar[fixvar_idx++].var; 864 v = &fc->fixvar[fixvar_idx++].var;
818 name = v->di_key; 865 name = v->di_key;
833 */ 880 */
834 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline", 881 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline",
835 (varnumber_T)firstline); 882 (varnumber_T)firstline);
836 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline", 883 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline",
837 (varnumber_T)lastline); 884 (varnumber_T)lastline);
838 for (i = 0; i < argcount; ++i) 885 for (i = 0; i < argcount || i < fp->uf_args.ga_len; ++i)
839 { 886 {
840 int addlocal = FALSE; 887 int addlocal = FALSE;
888 typval_T def_rettv;
889 int isdefault = FALSE;
841 890
842 ai = i - fp->uf_args.ga_len; 891 ai = i - fp->uf_args.ga_len;
843 if (ai < 0) 892 if (ai < 0)
844 { 893 {
845 /* named argument a:name */ 894 /* named argument a:name */
846 name = FUNCARG(fp, i); 895 name = FUNCARG(fp, i);
847 if (islambda) 896 if (islambda)
848 addlocal = TRUE; 897 addlocal = TRUE;
898
899 // evaluate named argument default expression
900 isdefault = ai + fp->uf_def_args.ga_len >= 0
901 && (i >= argcount || (argvars[i].v_type == VAR_SPECIAL
902 && argvars[i].vval.v_number == VVAL_NONE));
903 if (isdefault)
904 {
905 char_u *default_expr = NULL;
906 def_rettv.v_type = VAR_NUMBER;
907 def_rettv.vval.v_number = -1;
908
909 default_expr = ((char_u **)(fp->uf_def_args.ga_data))
910 [ai + fp->uf_def_args.ga_len];
911 if (eval1(&default_expr, &def_rettv, TRUE) == FAIL)
912 {
913 default_arg_err = 1;
914 break;
915 }
916 }
849 } 917 }
850 else 918 else
851 { 919 {
852 /* "..." argument a:1, a:2, etc. */ 920 /* "..." argument a:1, a:2, etc. */
853 sprintf((char *)numbuf, "%d", ai + 1); 921 sprintf((char *)numbuf, "%d", ai + 1);
865 if (v == NULL) 933 if (v == NULL)
866 break; 934 break;
867 v->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX; 935 v->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX;
868 } 936 }
869 937
870 /* Note: the values are copied directly to avoid alloc/free. 938 if (isdefault)
871 * "argvars" must have VAR_FIXED for v_lock. */ 939 v->di_tv = def_rettv;
872 v->di_tv = argvars[i]; 940 else
941 // Note: the values are copied directly to avoid alloc/free.
942 // "argvars" must have VAR_FIXED for v_lock.
943 v->di_tv = argvars[i];
873 v->di_tv.v_lock = VAR_FIXED; 944 v->di_tv.v_lock = VAR_FIXED;
874 945
875 if (addlocal) 946 if (addlocal)
876 { 947 {
877 /* Named arguments should be accessed without the "a:" prefix in 948 /* Named arguments should be accessed without the "a:" prefix in
986 save_current_sctx = current_sctx; 1057 save_current_sctx = current_sctx;
987 current_sctx = fp->uf_script_ctx; 1058 current_sctx = fp->uf_script_ctx;
988 save_did_emsg = did_emsg; 1059 save_did_emsg = did_emsg;
989 did_emsg = FALSE; 1060 did_emsg = FALSE;
990 1061
991 /* call do_cmdline() to execute the lines */ 1062 if (default_arg_err && (fp->uf_flags & FC_ABORT))
992 do_cmdline(NULL, get_func_line, (void *)fc, 1063 did_emsg = TRUE;
1064 else
1065 // call do_cmdline() to execute the lines
1066 do_cmdline(NULL, get_func_line, (void *)fc,
993 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT); 1067 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
994 1068
995 --RedrawingDisabled; 1069 --RedrawingDisabled;
996 1070
997 /* when the function was aborted because of an error, return -1 */ 1071 /* when the function was aborted because of an error, return -1 */
1143 1217
1144 static void 1218 static void
1145 func_clear_items(ufunc_T *fp) 1219 func_clear_items(ufunc_T *fp)
1146 { 1220 {
1147 ga_clear_strings(&(fp->uf_args)); 1221 ga_clear_strings(&(fp->uf_args));
1222 ga_clear_strings(&(fp->uf_def_args));
1148 ga_clear_strings(&(fp->uf_lines)); 1223 ga_clear_strings(&(fp->uf_lines));
1149 #ifdef FEAT_PROFILE 1224 #ifdef FEAT_PROFILE
1150 vim_free(fp->uf_tml_count); 1225 vim_free(fp->uf_tml_count);
1151 fp->uf_tml_count = NULL; 1226 fp->uf_tml_count = NULL;
1152 vim_free(fp->uf_tml_total); 1227 vim_free(fp->uf_tml_total);
1496 if (argv_func != NULL) 1571 if (argv_func != NULL)
1497 argcount = argv_func(argcount, argvars, fp->uf_args.ga_len); 1572 argcount = argv_func(argcount, argvars, fp->uf_args.ga_len);
1498 1573
1499 if (fp->uf_flags & FC_RANGE) 1574 if (fp->uf_flags & FC_RANGE)
1500 *doesrange = TRUE; 1575 *doesrange = TRUE;
1501 if (argcount < fp->uf_args.ga_len) 1576 if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len)
1502 error = ERROR_TOOFEW; 1577 error = ERROR_TOOFEW;
1503 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) 1578 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
1504 error = ERROR_TOOMANY; 1579 error = ERROR_TOOMANY;
1505 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) 1580 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
1506 error = ERROR_DICT; 1581 error = ERROR_DICT;
1622 for (j = 0; j < fp->uf_args.ga_len; ++j) 1697 for (j = 0; j < fp->uf_args.ga_len; ++j)
1623 { 1698 {
1624 if (j) 1699 if (j)
1625 msg_puts(", "); 1700 msg_puts(", ");
1626 msg_puts((char *)FUNCARG(fp, j)); 1701 msg_puts((char *)FUNCARG(fp, j));
1702 if (j >= fp->uf_args.ga_len - fp->uf_def_args.ga_len)
1703 {
1704 msg_puts(" = ");
1705 msg_puts(((char **)(fp->uf_def_args.ga_data))
1706 [j - fp->uf_args.ga_len + fp->uf_def_args.ga_len]);
1707 }
1627 } 1708 }
1628 if (fp->uf_varargs) 1709 if (fp->uf_varargs)
1629 { 1710 {
1630 if (j) 1711 if (j)
1631 msg_puts(", "); 1712 msg_puts(", ");
1887 char_u *name = NULL; 1968 char_u *name = NULL;
1888 char_u *p; 1969 char_u *p;
1889 char_u *arg; 1970 char_u *arg;
1890 char_u *line_arg = NULL; 1971 char_u *line_arg = NULL;
1891 garray_T newargs; 1972 garray_T newargs;
1973 garray_T default_args;
1892 garray_T newlines; 1974 garray_T newlines;
1893 int varargs = FALSE; 1975 int varargs = FALSE;
1894 int flags = 0; 1976 int flags = 0;
1895 ufunc_T *fp; 1977 ufunc_T *fp;
1896 int overwrite = FALSE; 1978 int overwrite = FALSE;
2101 /* Disallow using the g: dict. */ 2183 /* Disallow using the g: dict. */
2102 if (fudi.fd_dict != NULL && fudi.fd_dict->dv_scope == VAR_DEF_SCOPE) 2184 if (fudi.fd_dict != NULL && fudi.fd_dict->dv_scope == VAR_DEF_SCOPE)
2103 emsg(_("E862: Cannot use g: here")); 2185 emsg(_("E862: Cannot use g: here"));
2104 } 2186 }
2105 2187
2106 if (get_function_args(&p, ')', &newargs, &varargs, eap->skip) == FAIL) 2188 if (get_function_args(&p, ')', &newargs, &varargs,
2189 &default_args, eap->skip) == FAIL)
2107 goto errret_2; 2190 goto errret_2;
2108 2191
2109 /* find extra arguments "range", "dict", "abort" and "closure" */ 2192 /* find extra arguments "range", "dict", "abort" and "closure" */
2110 for (;;) 2193 for (;;)
2111 { 2194 {
2509 goto erret; 2592 goto erret;
2510 } 2593 }
2511 fp->uf_refcount = 1; 2594 fp->uf_refcount = 1;
2512 } 2595 }
2513 fp->uf_args = newargs; 2596 fp->uf_args = newargs;
2597 fp->uf_def_args = default_args;
2514 fp->uf_lines = newlines; 2598 fp->uf_lines = newlines;
2515 if ((flags & FC_CLOSURE) != 0) 2599 if ((flags & FC_CLOSURE) != 0)
2516 { 2600 {
2517 if (register_closure(fp) == FAIL) 2601 if (register_closure(fp) == FAIL)
2518 goto erret; 2602 goto erret;
2533 fp->uf_script_ctx.sc_lnum += sourcing_lnum - newlines.ga_len - 1; 2617 fp->uf_script_ctx.sc_lnum += sourcing_lnum - newlines.ga_len - 1;
2534 goto ret_free; 2618 goto ret_free;
2535 2619
2536 erret: 2620 erret:
2537 ga_clear_strings(&newargs); 2621 ga_clear_strings(&newargs);
2622 ga_clear_strings(&default_args);
2538 errret_2: 2623 errret_2:
2539 ga_clear_strings(&newlines); 2624 ga_clear_strings(&newlines);
2540 ret_free: 2625 ret_free:
2541 vim_free(skip_until); 2626 vim_free(skip_until);
2542 vim_free(line_to_free); 2627 vim_free(line_to_free);