comparison src/userfunc.c @ 31416:f088f1d97eee v9.0.1041

patch 9.0.1041: cannot define a method in a class Commit: https://github.com/vim/vim/commit/ffdaca9e6f3d39af6857ac52ced9385df203a152 Author: Bram Moolenaar <Bram@vim.org> Date: Fri Dec 9 21:41:48 2022 +0000 patch 9.0.1041: cannot define a method in a class Problem: Cannot define a method in a class. Solution: Implement defining an object method. Make calling an object method work.
author Bram Moolenaar <Bram@vim.org>
date Fri, 09 Dec 2022 22:45:03 +0100
parents 307f68a41b03
children e31fc75f6aff
comparison
equal deleted inserted replaced
31415:4fd33db887f2 31416:f088f1d97eee
186 else 186 else
187 theline = eap->getline(':', eap->cookie, indent, getline_options); 187 theline = eap->getline(':', eap->cookie, indent, getline_options);
188 if (theline != NULL) 188 if (theline != NULL)
189 { 189 {
190 if (lines_to_free->ga_len > 0 190 if (lines_to_free->ga_len > 0
191 && eap->cmdlinep != NULL
191 && *eap->cmdlinep == ((char_u **)lines_to_free->ga_data) 192 && *eap->cmdlinep == ((char_u **)lines_to_free->ga_data)
192 [lines_to_free->ga_len - 1]) 193 [lines_to_free->ga_len - 1])
193 *eap->cmdlinep = theline; 194 *eap->cmdlinep = theline;
194 ga_add_string(lines_to_free, theline); 195 ga_add_string(lines_to_free, theline);
195 } 196 }
212 evalarg_T *evalarg, // context or NULL 213 evalarg_T *evalarg, // context or NULL
213 int *varargs, 214 int *varargs,
214 garray_T *default_args, 215 garray_T *default_args,
215 int skip, 216 int skip,
216 exarg_T *eap, // can be NULL 217 exarg_T *eap, // can be NULL
217 class_T *class_arg, 218 int in_class, // TRUE when inside a class
218 garray_T *newlines, // function body lines 219 garray_T *newlines, // function body lines
219 garray_T *lines_to_free) 220 garray_T *lines_to_free)
220 { 221 {
221 int mustend = FALSE; 222 int mustend = FALSE;
222 char_u *arg; 223 char_u *arg;
292 emsg(_(e_cannot_use_default_for_variable_arguments)); 293 emsg(_(e_cannot_use_default_for_variable_arguments));
293 break; 294 break;
294 } 295 }
295 } 296 }
296 } 297 }
297 else if (class_arg != NULL && STRNCMP(p, "this.", 5) == 0) 298 else if (in_class && STRNCMP(p, "this.", 5) == 0)
298 { 299 {
299 // this.memberName 300 // this.memberName
300 p += 5; 301 p += 5;
301 arg = p; 302 arg = p;
302 while (ASCII_ISALNUM(*p) || *p == '_') 303 while (ASCII_ISALNUM(*p) || *p == '_')
1434 // First, check if this is really a lambda expression. "->" or "=>" must 1435 // First, check if this is really a lambda expression. "->" or "=>" must
1435 // be found after the arguments. 1436 // be found after the arguments.
1436 s = *arg + 1; 1437 s = *arg + 1;
1437 ret = get_function_args(&s, equal_arrow ? ')' : '-', NULL, 1438 ret = get_function_args(&s, equal_arrow ? ')' : '-', NULL,
1438 types_optional ? &argtypes : NULL, types_optional, evalarg, 1439 types_optional ? &argtypes : NULL, types_optional, evalarg,
1439 NULL, &default_args, TRUE, NULL, NULL, NULL, NULL); 1440 NULL, &default_args, TRUE, NULL, FALSE, NULL, NULL);
1440 if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type, NULL) == NULL) 1441 if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type, NULL) == NULL)
1441 { 1442 {
1442 if (types_optional) 1443 if (types_optional)
1443 ga_clear_strings(&argtypes); 1444 ga_clear_strings(&argtypes);
1444 return called_emsg == called_emsg_start ? NOTDONE : FAIL; 1445 return called_emsg == called_emsg_start ? NOTDONE : FAIL;
1451 pnewargs = NULL; 1452 pnewargs = NULL;
1452 *arg += 1; 1453 *arg += 1;
1453 ret = get_function_args(arg, equal_arrow ? ')' : '-', pnewargs, 1454 ret = get_function_args(arg, equal_arrow ? ')' : '-', pnewargs,
1454 types_optional ? &argtypes : NULL, types_optional, evalarg, 1455 types_optional ? &argtypes : NULL, types_optional, evalarg,
1455 &varargs, &default_args, 1456 &varargs, &default_args,
1456 FALSE, NULL, NULL, NULL, NULL); 1457 FALSE, NULL, FALSE, NULL, NULL);
1457 if (ret == FAIL 1458 if (ret == FAIL
1458 || (s = skip_arrow(*arg, equal_arrow, &ret_type, 1459 || (s = skip_arrow(*arg, equal_arrow, &ret_type,
1459 equal_arrow || vim9script ? &white_error : NULL)) == NULL) 1460 equal_arrow || vim9script ? &white_error : NULL)) == NULL)
1460 { 1461 {
1461 if (types_optional) 1462 if (types_optional)
2731 #ifdef FEAT_PROFILE 2732 #ifdef FEAT_PROFILE
2732 if (do_profiling == PROF_YES) 2733 if (do_profiling == PROF_YES)
2733 profile_may_start_func(&profile_info, fp, caller); 2734 profile_may_start_func(&profile_info, fp, caller);
2734 #endif 2735 #endif
2735 sticky_cmdmod_flags = 0; 2736 sticky_cmdmod_flags = 0;
2736 call_def_function(fp, argcount, argvars, 0, funcexe->fe_partial, 2737 call_def_function(fp, argcount, argvars, 0,
2737 fc, rettv); 2738 funcexe->fe_partial, funcexe->fe_object, fc, rettv);
2738 funcdepth_decrement(); 2739 funcdepth_decrement();
2739 #ifdef FEAT_PROFILE 2740 #ifdef FEAT_PROFILE
2740 if (do_profiling == PROF_YES && (fp->uf_profiling 2741 if (do_profiling == PROF_YES && (fp->uf_profiling
2741 || (caller != NULL && caller->uf_profiling))) 2742 || (caller != NULL && caller->uf_profiling)))
2742 profile_may_end_func(&profile_info, fp, caller); 2743 profile_may_end_func(&profile_info, fp, caller);
3955 * Returns the function name in allocated memory, or NULL for failure. 3956 * Returns the function name in allocated memory, or NULL for failure.
3956 * Set "*is_global" to TRUE when the function must be global, unless 3957 * Set "*is_global" to TRUE when the function must be global, unless
3957 * "is_global" is NULL. 3958 * "is_global" is NULL.
3958 * flags: 3959 * flags:
3959 * TFN_INT: internal function name OK 3960 * TFN_INT: internal function name OK
3961 * TFN_IN_CLASS: function in a class
3960 * TFN_QUIET: be quiet 3962 * TFN_QUIET: be quiet
3961 * TFN_NO_AUTOLOAD: do not use script autoloading 3963 * TFN_NO_AUTOLOAD: do not use script autoloading
3962 * TFN_NO_DEREF: do not dereference a Funcref 3964 * TFN_NO_DEREF: do not dereference a Funcref
3963 * Advances "pp" to just after the function name (if no error). 3965 * Advances "pp" to just after the function name (if no error).
3964 */ 3966 */
4170 emsg(_(e_function_name_required)); 4172 emsg(_(e_function_name_required));
4171 goto theend; 4173 goto theend;
4172 } 4174 }
4173 4175
4174 // In Vim9 script a user function is script-local by default, unless it 4176 // In Vim9 script a user function is script-local by default, unless it
4175 // starts with a lower case character: dict.func(). 4177 // starts with a lower case character: dict.func(). Or when in a class.
4176 vim9_local = ASCII_ISUPPER(*start) && vim9script; 4178 vim9_local = ASCII_ISUPPER(*start) && vim9script
4179 && (flags & TFN_IN_CLASS) == 0;
4177 4180
4178 /* 4181 /*
4179 * Copy the function name to allocated memory. 4182 * Copy the function name to allocated memory.
4180 * Accept <SID>name() inside a script, translate into <SNR>123_name(). 4183 * Accept <SID>name() inside a script, translate into <SNR>123_name().
4181 * Accept <SNR>123_name() outside a script. 4184 * Accept <SNR>123_name() outside a script.
4209 extra = 3 + (int)STRLEN(sid_buf); 4212 extra = 3 + (int)STRLEN(sid_buf);
4210 else 4213 else
4211 lead += (int)STRLEN(sid_buf); 4214 lead += (int)STRLEN(sid_buf);
4212 } 4215 }
4213 } 4216 }
4214 else if (!(flags & TFN_INT) && (builtin_function(lv.ll_name, len) 4217 else if (!(flags & TFN_INT)
4215 || (vim9script && *lv.ll_name == '_'))) 4218 && (builtin_function(lv.ll_name, len)
4219 || (vim9script && *lv.ll_name == '_'))
4220 && !((flags & TFN_IN_CLASS) && STRNCMP(lv.ll_name, "new", 3) == 0))
4216 { 4221 {
4217 semsg(_(vim9script ? e_function_name_must_start_with_capital_str 4222 semsg(_(vim9script ? e_function_name_must_start_with_capital_str
4218 : e_function_name_must_start_with_capital_or_s_str), 4223 : e_function_name_must_start_with_capital_or_s_str),
4219 start); 4224 start);
4220 goto theend; 4225 goto theend;
4415 /* 4420 /*
4416 * ":function" also supporting nested ":def". 4421 * ":function" also supporting nested ":def".
4417 * When "name_arg" is not NULL this is a nested function, using "name_arg" for 4422 * When "name_arg" is not NULL this is a nested function, using "name_arg" for
4418 * the function name. 4423 * the function name.
4419 * "lines_to_free" is a list of strings to be freed later. 4424 * "lines_to_free" is a list of strings to be freed later.
4420 * If "class_arg" is not NULL then the function is defined in this class. 4425 * If "in_class" is TRUE then the function is defined inside a class.
4421 * Returns a pointer to the function or NULL if no function defined. 4426 * Returns a pointer to the function or NULL if no function defined.
4422 */ 4427 */
4423 ufunc_T * 4428 ufunc_T *
4424 define_function( 4429 define_function(
4425 exarg_T *eap, 4430 exarg_T *eap,
4426 char_u *name_arg, 4431 char_u *name_arg,
4427 garray_T *lines_to_free, 4432 garray_T *lines_to_free,
4428 class_T *class_arg) 4433 int in_class)
4429 { 4434 {
4430 int j; 4435 int j;
4431 int c; 4436 int c;
4432 int saved_did_emsg = FALSE; 4437 int saved_did_emsg = FALSE;
4433 char_u *name = name_arg; 4438 char_u *name = name_arg;
4498 ga_init(&argtypes); 4503 ga_init(&argtypes);
4499 ga_init(&default_args); 4504 ga_init(&default_args);
4500 4505
4501 /* 4506 /*
4502 * Get the function name. There are these situations: 4507 * Get the function name. There are these situations:
4503 * func normal function name 4508 * func normal function name, also when "in_class" is TRUE
4504 * "name" == func, "fudi.fd_dict" == NULL 4509 * "name" == func, "fudi.fd_dict" == NULL
4505 * dict.func new dictionary entry 4510 * dict.func new dictionary entry
4506 * "name" == NULL, "fudi.fd_dict" set, 4511 * "name" == NULL, "fudi.fd_dict" set,
4507 * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func 4512 * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
4508 * dict.func existing dict entry with a Funcref 4513 * dict.func existing dict entry with a Funcref
4539 } 4544 }
4540 p = eap->arg; 4545 p = eap->arg;
4541 } 4546 }
4542 4547
4543 int tfn_flags = TFN_NO_AUTOLOAD | TFN_NEW_FUNC 4548 int tfn_flags = TFN_NO_AUTOLOAD | TFN_NEW_FUNC
4544 | (class_arg == 0 ? 0 : TFN_INT); 4549 | (in_class ? TFN_IN_CLASS : 0);
4545 name = save_function_name(&p, &is_global, eap->skip, tfn_flags, &fudi); 4550 name = save_function_name(&p, &is_global, eap->skip, tfn_flags, &fudi);
4546 paren = (vim_strchr(p, '(') != NULL); 4551 paren = (vim_strchr(p, '(') != NULL);
4547 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) 4552 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
4548 { 4553 {
4549 /* 4554 /*
4741 // invalid. 4746 // invalid.
4742 ++p; 4747 ++p;
4743 if (get_function_args(&p, ')', &newargs, 4748 if (get_function_args(&p, ')', &newargs,
4744 eap->cmdidx == CMD_def ? &argtypes : NULL, FALSE, 4749 eap->cmdidx == CMD_def ? &argtypes : NULL, FALSE,
4745 NULL, &varargs, &default_args, eap->skip, 4750 NULL, &varargs, &default_args, eap->skip,
4746 eap, class_arg, &newlines, lines_to_free) == FAIL) 4751 eap, in_class, &newlines, lines_to_free) == FAIL)
4747 goto errret_2; 4752 goto errret_2;
4748 whitep = p; 4753 whitep = p;
4749 4754
4750 if (eap->cmdidx == CMD_def) 4755 if (eap->cmdidx == CMD_def)
4751 { 4756 {
4858 goto erret; 4863 goto erret;
4859 4864
4860 /* 4865 /*
4861 * If there are no errors, add the function 4866 * If there are no errors, add the function
4862 */ 4867 */
4863 if (fudi.fd_dict == NULL) 4868 if (fudi.fd_dict != NULL)
4869 {
4870 char numbuf[20];
4871
4872 fp = NULL;
4873 if (fudi.fd_newkey == NULL && !eap->forceit)
4874 {
4875 emsg(_(e_dictionary_entry_already_exists));
4876 goto erret;
4877 }
4878 if (fudi.fd_di == NULL)
4879 {
4880 // Can't add a function to a locked dictionary
4881 if (value_check_lock(fudi.fd_dict->dv_lock, eap->arg, FALSE))
4882 goto erret;
4883 }
4884 // Can't change an existing function if it is locked
4885 else if (value_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, FALSE))
4886 goto erret;
4887
4888 // Give the function a sequential number. Can only be used with a
4889 // Funcref!
4890 vim_free(name);
4891 sprintf(numbuf, "%d", ++func_nr);
4892 name = vim_strsave((char_u *)numbuf);
4893 if (name == NULL)
4894 goto erret;
4895 }
4896 else if (!in_class)
4864 { 4897 {
4865 hashtab_T *ht; 4898 hashtab_T *ht;
4866 char_u *find_name = name; 4899 char_u *find_name = name;
4867 int var_conflict = FALSE; 4900 int var_conflict = FALSE;
4868 int ffed_flags = is_global ? FFED_IS_GLOBAL : 0; 4901 int ffed_flags = is_global ? FFED_IS_GLOBAL : 0;
4964 fp->uf_prof_initialized = FALSE; 4997 fp->uf_prof_initialized = FALSE;
4965 #endif 4998 #endif
4966 fp->uf_def_status = UF_NOT_COMPILED; 4999 fp->uf_def_status = UF_NOT_COMPILED;
4967 } 5000 }
4968 } 5001 }
4969 }
4970 else
4971 {
4972 char numbuf[20];
4973
4974 fp = NULL;
4975 if (fudi.fd_newkey == NULL && !eap->forceit)
4976 {
4977 emsg(_(e_dictionary_entry_already_exists));
4978 goto erret;
4979 }
4980 if (fudi.fd_di == NULL)
4981 {
4982 // Can't add a function to a locked dictionary
4983 if (value_check_lock(fudi.fd_dict->dv_lock, eap->arg, FALSE))
4984 goto erret;
4985 }
4986 // Can't change an existing function if it is locked
4987 else if (value_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, FALSE))
4988 goto erret;
4989
4990 // Give the function a sequential number. Can only be used with a
4991 // Funcref!
4992 vim_free(name);
4993 sprintf(numbuf, "%d", ++func_nr);
4994 name = vim_strsave((char_u *)numbuf);
4995 if (name == NULL)
4996 goto erret;
4997 } 5002 }
4998 5003
4999 if (fp == NULL) 5004 if (fp == NULL)
5000 { 5005 {
5001 if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL) 5006 if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL)
5111 if (overwrite) 5116 if (overwrite)
5112 { 5117 {
5113 hi = hash_find(&func_hashtab, name); 5118 hi = hash_find(&func_hashtab, name);
5114 hi->hi_key = UF2HIKEY(fp); 5119 hi->hi_key = UF2HIKEY(fp);
5115 } 5120 }
5116 else if (hash_add(&func_hashtab, UF2HIKEY(fp), "add function") == FAIL) 5121 else if (!in_class && hash_add(&func_hashtab,
5122 UF2HIKEY(fp), "add function") == FAIL)
5117 { 5123 {
5118 free_fp = TRUE; 5124 free_fp = TRUE;
5119 goto erret; 5125 goto erret;
5120 } 5126 }
5121 fp->uf_refcount = 1; 5127 fp->uf_refcount = 1;
5196 ex_function(exarg_T *eap) 5202 ex_function(exarg_T *eap)
5197 { 5203 {
5198 garray_T lines_to_free; 5204 garray_T lines_to_free;
5199 5205
5200 ga_init2(&lines_to_free, sizeof(char_u *), 50); 5206 ga_init2(&lines_to_free, sizeof(char_u *), 50);
5201 (void)define_function(eap, NULL, &lines_to_free, NULL); 5207 (void)define_function(eap, NULL, &lines_to_free, FALSE);
5202 ga_clear_strings(&lines_to_free); 5208 ga_clear_strings(&lines_to_free);
5203 } 5209 }
5204 5210
5205 /* 5211 /*
5206 * Find a function by name, including "<lambda>123". 5212 * Find a function by name, including "<lambda>123".