diff options
author | Bram Moolenaar <Bram@vim.org> | 2022-12-09 21:41:48 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-12-09 21:41:48 +0000 |
commit | ffdaca9e6f3d39af6857ac52ced9385df203a152 (patch) | |
tree | 04ed8cbe05e072413dd394828d7661167ad63b6c /src/userfunc.c | |
parent | 148bcd361097f85a1a51c408e7412d60c76df14d (diff) | |
download | vim-git-ffdaca9e6f3d39af6857ac52ced9385df203a152.tar.gz |
patch 9.0.1041: cannot define a method in a classv9.0.1041
Problem: Cannot define a method in a class.
Solution: Implement defining an object method. Make calling an object
method work.
Diffstat (limited to 'src/userfunc.c')
-rw-r--r-- | src/userfunc.c | 98 |
1 files changed, 52 insertions, 46 deletions
diff --git a/src/userfunc.c b/src/userfunc.c index 5db0b709c..ac7c4fde5 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -188,6 +188,7 @@ get_function_line( if (theline != NULL) { if (lines_to_free->ga_len > 0 + && eap->cmdlinep != NULL && *eap->cmdlinep == ((char_u **)lines_to_free->ga_data) [lines_to_free->ga_len - 1]) *eap->cmdlinep = theline; @@ -214,7 +215,7 @@ get_function_args( garray_T *default_args, int skip, exarg_T *eap, // can be NULL - class_T *class_arg, + int in_class, // TRUE when inside a class garray_T *newlines, // function body lines garray_T *lines_to_free) { @@ -294,7 +295,7 @@ get_function_args( } } } - else if (class_arg != NULL && STRNCMP(p, "this.", 5) == 0) + else if (in_class && STRNCMP(p, "this.", 5) == 0) { // this.memberName p += 5; @@ -1436,7 +1437,7 @@ get_lambda_tv( s = *arg + 1; ret = get_function_args(&s, equal_arrow ? ')' : '-', NULL, types_optional ? &argtypes : NULL, types_optional, evalarg, - NULL, &default_args, TRUE, NULL, NULL, NULL, NULL); + NULL, &default_args, TRUE, NULL, FALSE, NULL, NULL); if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type, NULL) == NULL) { if (types_optional) @@ -1453,7 +1454,7 @@ get_lambda_tv( ret = get_function_args(arg, equal_arrow ? ')' : '-', pnewargs, types_optional ? &argtypes : NULL, types_optional, evalarg, &varargs, &default_args, - FALSE, NULL, NULL, NULL, NULL); + FALSE, NULL, FALSE, NULL, NULL); if (ret == FAIL || (s = skip_arrow(*arg, equal_arrow, &ret_type, equal_arrow || vim9script ? &white_error : NULL)) == NULL) @@ -2733,8 +2734,8 @@ call_user_func( profile_may_start_func(&profile_info, fp, caller); #endif sticky_cmdmod_flags = 0; - call_def_function(fp, argcount, argvars, 0, funcexe->fe_partial, - fc, rettv); + call_def_function(fp, argcount, argvars, 0, + funcexe->fe_partial, funcexe->fe_object, fc, rettv); funcdepth_decrement(); #ifdef FEAT_PROFILE if (do_profiling == PROF_YES && (fp->uf_profiling @@ -3957,6 +3958,7 @@ list_func_head(ufunc_T *fp, int indent) * "is_global" is NULL. * flags: * TFN_INT: internal function name OK + * TFN_IN_CLASS: function in a class * TFN_QUIET: be quiet * TFN_NO_AUTOLOAD: do not use script autoloading * TFN_NO_DEREF: do not dereference a Funcref @@ -4172,8 +4174,9 @@ trans_function_name( } // In Vim9 script a user function is script-local by default, unless it - // starts with a lower case character: dict.func(). - vim9_local = ASCII_ISUPPER(*start) && vim9script; + // starts with a lower case character: dict.func(). Or when in a class. + vim9_local = ASCII_ISUPPER(*start) && vim9script + && (flags & TFN_IN_CLASS) == 0; /* * Copy the function name to allocated memory. @@ -4211,8 +4214,10 @@ trans_function_name( lead += (int)STRLEN(sid_buf); } } - else if (!(flags & TFN_INT) && (builtin_function(lv.ll_name, len) - || (vim9script && *lv.ll_name == '_'))) + else if (!(flags & TFN_INT) + && (builtin_function(lv.ll_name, len) + || (vim9script && *lv.ll_name == '_')) + && !((flags & TFN_IN_CLASS) && STRNCMP(lv.ll_name, "new", 3) == 0)) { semsg(_(vim9script ? e_function_name_must_start_with_capital_str : e_function_name_must_start_with_capital_or_s_str), @@ -4417,7 +4422,7 @@ list_functions(regmatch_T *regmatch) * When "name_arg" is not NULL this is a nested function, using "name_arg" for * the function name. * "lines_to_free" is a list of strings to be freed later. - * If "class_arg" is not NULL then the function is defined in this class. + * If "in_class" is TRUE then the function is defined inside a class. * Returns a pointer to the function or NULL if no function defined. */ ufunc_T * @@ -4425,7 +4430,7 @@ define_function( exarg_T *eap, char_u *name_arg, garray_T *lines_to_free, - class_T *class_arg) + int in_class) { int j; int c; @@ -4500,7 +4505,7 @@ define_function( /* * Get the function name. There are these situations: - * func normal function name + * func normal function name, also when "in_class" is TRUE * "name" == func, "fudi.fd_dict" == NULL * dict.func new dictionary entry * "name" == NULL, "fudi.fd_dict" set, @@ -4541,7 +4546,7 @@ define_function( } int tfn_flags = TFN_NO_AUTOLOAD | TFN_NEW_FUNC - | (class_arg == 0 ? 0 : TFN_INT); + | (in_class ? TFN_IN_CLASS : 0); name = save_function_name(&p, &is_global, eap->skip, tfn_flags, &fudi); paren = (vim_strchr(p, '(') != NULL); if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) @@ -4743,7 +4748,7 @@ define_function( if (get_function_args(&p, ')', &newargs, eap->cmdidx == CMD_def ? &argtypes : NULL, FALSE, NULL, &varargs, &default_args, eap->skip, - eap, class_arg, &newlines, lines_to_free) == FAIL) + eap, in_class, &newlines, lines_to_free) == FAIL) goto errret_2; whitep = p; @@ -4860,7 +4865,35 @@ define_function( /* * If there are no errors, add the function */ - if (fudi.fd_dict == NULL) + if (fudi.fd_dict != NULL) + { + char numbuf[20]; + + fp = NULL; + if (fudi.fd_newkey == NULL && !eap->forceit) + { + emsg(_(e_dictionary_entry_already_exists)); + goto erret; + } + if (fudi.fd_di == NULL) + { + // Can't add a function to a locked dictionary + if (value_check_lock(fudi.fd_dict->dv_lock, eap->arg, FALSE)) + goto erret; + } + // Can't change an existing function if it is locked + else if (value_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, FALSE)) + goto erret; + + // Give the function a sequential number. Can only be used with a + // Funcref! + vim_free(name); + sprintf(numbuf, "%d", ++func_nr); + name = vim_strsave((char_u *)numbuf); + if (name == NULL) + goto erret; + } + else if (!in_class) { hashtab_T *ht; char_u *find_name = name; @@ -4967,34 +5000,6 @@ define_function( } } } - else - { - char numbuf[20]; - - fp = NULL; - if (fudi.fd_newkey == NULL && !eap->forceit) - { - emsg(_(e_dictionary_entry_already_exists)); - goto erret; - } - if (fudi.fd_di == NULL) - { - // Can't add a function to a locked dictionary - if (value_check_lock(fudi.fd_dict->dv_lock, eap->arg, FALSE)) - goto erret; - } - // Can't change an existing function if it is locked - else if (value_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, FALSE)) - goto erret; - - // Give the function a sequential number. Can only be used with a - // Funcref! - vim_free(name); - sprintf(numbuf, "%d", ++func_nr); - name = vim_strsave((char_u *)numbuf); - if (name == NULL) - goto erret; - } if (fp == NULL) { @@ -5113,7 +5118,8 @@ define_function( hi = hash_find(&func_hashtab, name); hi->hi_key = UF2HIKEY(fp); } - else if (hash_add(&func_hashtab, UF2HIKEY(fp), "add function") == FAIL) + else if (!in_class && hash_add(&func_hashtab, + UF2HIKEY(fp), "add function") == FAIL) { free_fp = TRUE; goto erret; @@ -5198,7 +5204,7 @@ ex_function(exarg_T *eap) garray_T lines_to_free; ga_init2(&lines_to_free, sizeof(char_u *), 50); - (void)define_function(eap, NULL, &lines_to_free, NULL); + (void)define_function(eap, NULL, &lines_to_free, FALSE); ga_clear_strings(&lines_to_free); } |