Mercurial > vim
comparison src/vim9expr.c @ 27457:4c16acb2525f v8.2.4257
patch 8.2.4257: Vim9: finding global function without g: prefix inconsistent
Commit: https://github.com/vim/vim/commit/62aec93bfdb9e1b40d03a6d2e8e9511f8b1bdb2d
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jan 29 21:45:34 2022 +0000
patch 8.2.4257: Vim9: finding global function without g: prefix inconsistent
Problem: Vim9: finding global function without g: prefix but not finding
global variable is inconsistent.
Solution: Require using g: for a global function. Change the vim9.vim
script into a Vim9 script with exports. Fix that import in legacy
script does not work.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 29 Jan 2022 23:00:05 +0100 |
parents | 1a6421c5be20 |
children | a14c4d3e3260 |
comparison
equal
deleted
inserted
replaced
27456:a8e2d91995ce | 27457:4c16acb2525f |
---|---|
252 | 252 |
253 if (!SCRIPT_ID_VALID(current_sctx.sc_sid)) | 253 if (!SCRIPT_ID_VALID(current_sctx.sc_sid)) |
254 return FAIL; | 254 return FAIL; |
255 si = SCRIPT_ITEM(current_sctx.sc_sid); | 255 si = SCRIPT_ITEM(current_sctx.sc_sid); |
256 idx = get_script_item_idx(current_sctx.sc_sid, name, 0, cctx); | 256 idx = get_script_item_idx(current_sctx.sc_sid, name, 0, cctx); |
257 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9) | |
258 { | |
259 // variable is not in sn_var_vals: old style script. | |
260 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid, | |
261 &t_any); | |
262 } | |
263 if (idx >= 0) | 257 if (idx >= 0) |
264 { | 258 { |
265 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; | 259 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; |
266 | 260 |
267 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT, | 261 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT, |
341 import->imp_sid, | 335 import->imp_sid, |
342 idx, | 336 idx, |
343 type); | 337 type); |
344 return OK; | 338 return OK; |
345 } | 339 } |
340 | |
341 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9) | |
342 // variable is not in sn_var_vals: old style script. | |
343 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid, | |
344 &t_any); | |
346 | 345 |
347 if (error) | 346 if (error) |
348 semsg(_(e_item_not_found_str), name); | 347 semsg(_(e_item_not_found_str), name); |
349 return FAIL; | 348 return FAIL; |
350 } | 349 } |
665 char_u *tofree = NULL; | 664 char_u *tofree = NULL; |
666 int error = FCERR_NONE; | 665 int error = FCERR_NONE; |
667 ufunc_T *ufunc = NULL; | 666 ufunc_T *ufunc = NULL; |
668 int res = FAIL; | 667 int res = FAIL; |
669 int is_autoload; | 668 int is_autoload; |
669 int has_g_namespace; | |
670 int is_searchpair; | 670 int is_searchpair; |
671 imported_T *import; | 671 imported_T *import; |
672 | 672 |
673 if (varlen >= sizeof(namebuf)) | 673 if (varlen >= sizeof(namebuf)) |
674 { | 674 { |
781 else | 781 else |
782 semsg(_(e_unknown_function_str), namebuf); | 782 semsg(_(e_unknown_function_str), namebuf); |
783 goto theend; | 783 goto theend; |
784 } | 784 } |
785 | 785 |
786 has_g_namespace = STRNCMP(namebuf, "g:", 2) == 0; | |
787 | |
786 // An argument or local variable can be a function reference, this | 788 // An argument or local variable can be a function reference, this |
787 // overrules a function name. | 789 // overrules a function name. |
788 if (lookup_local(namebuf, varlen, NULL, cctx) == FAIL | 790 if (lookup_local(namebuf, varlen, NULL, cctx) == FAIL |
789 && arg_exists(namebuf, varlen, NULL, NULL, NULL, cctx) != OK) | 791 && arg_exists(namebuf, varlen, NULL, NULL, NULL, cctx) != OK) |
790 { | 792 { |
791 // If we can find the function by name generate the right call. | 793 // If we can find the function by name generate the right call. |
792 // Skip global functions here, a local funcref takes precedence. | 794 // Skip global functions here, a local funcref takes precedence. |
793 ufunc = find_func(name, FALSE); | 795 ufunc = find_func(name, FALSE); |
794 if (ufunc != NULL && !func_is_global(ufunc)) | 796 if (ufunc != NULL) |
795 { | 797 { |
796 res = generate_CALL(cctx, ufunc, argcount); | 798 if (!func_is_global(ufunc)) |
797 goto theend; | 799 { |
800 res = generate_CALL(cctx, ufunc, argcount); | |
801 goto theend; | |
802 } | |
803 if (!has_g_namespace | |
804 && vim_strchr(ufunc->uf_name, AUTOLOAD_CHAR) == NULL) | |
805 { | |
806 // A function name without g: prefix must be found locally. | |
807 semsg(_(e_unknown_function_str), namebuf); | |
808 goto theend; | |
809 } | |
798 } | 810 } |
799 } | 811 } |
800 | 812 |
801 // If the name is a variable, load it and use PCALL. | 813 // If the name is a variable, load it and use PCALL. |
802 // Not for g:Func(), we don't know if it is a variable or not. | 814 // Not for g:Func(), we don't know if it is a variable or not. |
803 // Not for eome#Func(), it will be loaded later. | 815 // Not for eome#Func(), it will be loaded later. |
804 p = namebuf; | 816 p = namebuf; |
805 if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload | 817 if (!has_g_namespace && !is_autoload |
806 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK) | 818 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK) |
807 { | 819 { |
808 type_T *type = get_type_on_stack(cctx, 0); | 820 type_T *type = get_type_on_stack(cctx, 0); |
809 | 821 |
810 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE); | 822 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE); |
818 goto theend; | 830 goto theend; |
819 } | 831 } |
820 | 832 |
821 // A global function may be defined only later. Need to figure out at | 833 // A global function may be defined only later. Need to figure out at |
822 // runtime. Also handles a FuncRef at runtime. | 834 // runtime. Also handles a FuncRef at runtime. |
823 if (STRNCMP(namebuf, "g:", 2) == 0 || is_autoload) | 835 if (has_g_namespace || is_autoload) |
824 res = generate_UCALL(cctx, name, argcount); | 836 res = generate_UCALL(cctx, name, argcount); |
825 else | 837 else |
826 semsg(_(e_unknown_function_str), namebuf); | 838 semsg(_(e_unknown_function_str), namebuf); |
827 | 839 |
828 theend: | 840 theend: |