To: vim_dev@googlegroups.com Subject: Patch 8.2.4019 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ NOTE: this changes the syntax of the :import command. If you use :import you will need to adjust your scripts. If you see a problem with the new syntax, please let me know, to avoid making an incompatible change twice. Patch 8.2.4019 Problem: Vim9: import mechanism is too complicated. Solution: Do not use the Javascript mechanism but a much simpler one. Files: runtime/doc/vim9.txt, src/vim9script.c, src/proto/vim9script.pro, src/errors.h, src/structs.h, src/eval.c, src/proto/eval.pro, src/evalvars.c, src/proto/evalvars.pro, src/userfunc.c, src/vim9expr.c, src/vim9compile.c, src/vim9execute.c, src/testdir/test_vim9_assign.vim, src/testdir/test_vim9_script.vim *** ../vim-8.2.4018/runtime/doc/vim9.txt 2022-01-01 12:16:56.436066976 +0000 --- runtime/doc/vim9.txt 2022-01-06 20:16:17.915283316 +0000 *************** *** 1432,1455 **** Import ~ *:import* *:imp* *E1094* ! The exported items can be imported individually in another Vim9 script: > ! import EXPORTED_CONST from "thatscript.vim" ! import MyClass from "myclass.vim" ! ! To import multiple items at the same time: > ! import {someValue, MyClass} from "thatscript.vim" ! ! In case the name is ambiguous, another name can be specified: > ! import MyClass as ThatClass from "myclass.vim" ! import {someValue, MyClass as ThatClass} from "myclass.vim" ! To import all exported items under a specific identifier: > ! import * as That from 'thatscript.vim' Then you can use "That.EXPORTED_CONST", "That.someValue", etc. You are free ! to choose the name "That", but it is highly recommended to use the name of the ! script file to avoid confusion. Also avoid command names, because the name ! will shadow them. `:import` can also be used in legacy Vim script. The imported items still become script-local, even when the "s:" prefix is not given. --- 1432,1458 ---- Import ~ *:import* *:imp* *E1094* ! The exported items can be imported in another Vim9 script: > ! import "myscript.vim" ! This makes each item available as "myscript.item". ! ! In case the name is long or ambiguous, another name can be specified: > ! import "thatscript.vim" as That Then you can use "That.EXPORTED_CONST", "That.someValue", etc. You are free ! to choose the name "That". Use something that will be recognized as referring ! to the imported script. Avoid command names, because the name will shadow ! them. ! ! In case the dot in the name is unwanted, a local reference can be made: > ! var ThatFunc = That.LongFuncName ! ! This also works for constants: > ! cost MAXLEN = That.MAX_LEN_OF_NAME ! ! This does not work for variables, you could use a setter function and make a ! local reference for it. `:import` can also be used in legacy Vim script. The imported items still become script-local, even when the "s:" prefix is not given. *************** *** 1470,1475 **** --- 1473,1481 ---- Once a vim9 script file has been imported, the result is cached and used the next time the same script is imported. It will not be read again. + + It is not allowed to import the same script twice, also when using two + different "as" names. *:import-cycle* The `import` commands are executed when encountered. If that script (directly or indirectly) imports the current script, then items defined after the *************** *** 1491,1499 **** 2. In the autoload script do the actual work. You can import items from other files to split up functionality in appropriate pieces. > vim9script ! import FilterFunc from "../import/someother.vim" def searchfor#Stuff(arg: string) ! var filtered = FilterFunc(arg) ... < This goes in .../autoload/searchfor.vim. "searchfor" in the file name must be exactly the same as the prefix for the function name, that is how --- 1497,1505 ---- 2. In the autoload script do the actual work. You can import items from other files to split up functionality in appropriate pieces. > vim9script ! import "../import/someother.vim" as other def searchfor#Stuff(arg: string) ! var filtered = other.FilterFunc(arg) ... < This goes in .../autoload/searchfor.vim. "searchfor" in the file name must be exactly the same as the prefix for the function name, that is how *** ../vim-8.2.4018/src/vim9script.c 2022-01-03 12:27:59.359039951 +0000 --- src/vim9script.c 2022-01-06 20:33:16.553129524 +0000 *************** *** 363,483 **** void *cctx) { char_u *arg = arg_start; ! char_u *cmd_end = NULL; int ret = FAIL; typval_T tv; int sid = -1; int res; - int mult = FALSE; - garray_T names; - garray_T as_names; long start_lnum = SOURCING_LNUM; - tv.v_type = VAR_UNKNOWN; - ga_init2(&names, sizeof(char_u *), 10); - ga_init2(&as_names, sizeof(char_u *), 10); - if (*arg == '{') - { - // "import {item, item} from ..." - mult = TRUE; - arg = skipwhite_and_linebreak(arg + 1, evalarg); - } - - for (;;) - { - char_u *p = arg; - int had_comma = FALSE; - char_u *as_name = NULL; - - // accept "*" or "Name" - if (!mult && arg[0] == '*' && IS_WHITE_OR_NUL(arg[1])) - ++arg; - else - while (eval_isnamec(*arg)) - ++arg; - if (p == arg) - break; - if (ga_grow(&names, 1) == FAIL || ga_grow(&as_names, 1) == FAIL) - goto erret; - ((char_u **)names.ga_data)[names.ga_len] = vim_strnsave(p, arg - p); - ++names.ga_len; - - arg = skipwhite_and_linebreak(arg, evalarg); - if (STRNCMP("as", arg, 2) == 0 && IS_WHITE_OR_NUL(arg[2])) - { - // Skip over "as Name "; no line break allowed after "as". - // Do not allow for ':' and '#'. - arg = skipwhite(arg + 2); - p = arg; - if (eval_isnamec1(*arg)) - while (ASCII_ISALNUM(*arg) || *arg == '_') - ++arg; - if (p == arg || !(IS_WHITE_OR_NUL(*arg) - || (mult && (*arg == ',' || *arg == '}')))) - { - semsg(_(e_syntax_error_in_import_str), p); - goto erret; - } - if (check_defined(p, arg - p, cctx, FALSE) == FAIL) - goto erret; - as_name = vim_strnsave(p, arg - p); - arg = skipwhite_and_linebreak(arg, evalarg); - } - else if (*arg_start == '*') - { - emsg(_(e_missing_as_after_star)); - goto erret; - } - // without "as Name" the as_names entry is NULL - ((char_u **)as_names.ga_data)[as_names.ga_len] = as_name; - ++as_names.ga_len; - - if (!mult) - break; - if (*arg == ',') - { - had_comma = TRUE; - ++arg; - } - arg = skipwhite_and_linebreak(arg, evalarg); - if (*arg == '}') - { - ++arg; - break; - } - if (!had_comma) - { - emsg(_(e_missing_comma_in_import)); - goto erret; - } - } - arg = skipwhite_and_linebreak(arg, evalarg); - - if (names.ga_len == 0) - { - semsg(_(e_syntax_error_in_import_str), arg_start); - goto erret; - } - - if (STRNCMP("from", arg, 4) != 0 || !IS_WHITE_OR_NUL(arg[4])) - { - emsg(_(e_missing_from)); - goto erret; - } - // The name of the file can be an expression, which must evaluate to a // string. ! arg = skipwhite_and_linebreak(arg + 4, evalarg); ! ret = eval0(arg, &tv, NULL, evalarg); if (ret == FAIL) goto erret; if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL || *tv.vval.v_string == NUL) { ! emsg(_(e_invalid_string_after_from)); goto erret; } - cmd_end = arg; // Give error messages for the start of the line. SOURCING_LNUM = start_lnum; --- 363,389 ---- void *cctx) { char_u *arg = arg_start; ! char_u *nextarg; ! int getnext; ! char_u *expr_end; int ret = FAIL; + char_u *as_name = NULL; typval_T tv; int sid = -1; int res; long start_lnum = SOURCING_LNUM; // The name of the file can be an expression, which must evaluate to a // string. ! ret = eval0_retarg(arg, &tv, NULL, evalarg, &expr_end); if (ret == FAIL) goto erret; if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL || *tv.vval.v_string == NUL) { ! semsg(_(e_invalid_string_for_import_str), arg); goto erret; } // Give error messages for the start of the line. SOURCING_LNUM = start_lnum; *************** *** 532,543 **** goto erret; } ! if (*arg_start == '*') { imported_T *imported; - char_u *as_name = ((char_u **)as_names.ga_data)[0]; - // "import * as That" imported = find_imported(as_name, STRLEN(as_name), cctx); if (imported != NULL && imported->imp_sid == sid) { --- 438,492 ---- goto erret; } ! // Allow for the "as Name" to be in the next line. ! nextarg = eval_next_non_blank(expr_end, evalarg, &getnext); ! if (STRNCMP("as", nextarg, 2) == 0 && IS_WHITE_OR_NUL(nextarg[2])) ! { ! char_u *p; ! ! if (getnext) ! arg = eval_next_line(evalarg); ! else ! arg = nextarg; ! ! // Skip over "as Name "; no line break allowed after "as". ! // Do not allow for ':' and '#'. ! arg = skipwhite(arg + 2); ! p = arg; ! if (eval_isnamec1(*arg)) ! while (ASCII_ISALNUM(*arg) || *arg == '_') ! ++arg; ! if (p == arg || !IS_WHITE_OR_NUL(*arg)) ! { ! semsg(_(e_syntax_error_in_import_str), p); ! goto erret; ! } ! as_name = vim_strnsave(p, arg - p); ! arg = skipwhite(arg); ! } ! else ! { ! char_u *p = gettail(tv.vval.v_string); ! char_u *end = (char_u *)strstr((char *)p, ".vim"); ! ! if (!ends_excmd2(arg_start, expr_end)) ! { ! semsg(_(e_trailing_characters_str), expr_end); ! goto erret; ! } ! ! if (end == NULL) ! { ! semsg(_(e_imported_script_must_end_in_dot_vim_str), p); ! goto erret; ! } ! as_name = vim_strnsave(p, end - p); ! } ! ! if (as_name != NULL) { imported_T *imported; imported = find_imported(as_name, STRLEN(as_name), cctx); if (imported != NULL && imported->imp_sid == sid) { *************** *** 550,656 **** goto erret; } } imported = new_imported(gap != NULL ? gap : &SCRIPT_ITEM(import_sid)->sn_imports); if (imported == NULL) goto erret; imported->imp_name = as_name; ! ((char_u **)as_names.ga_data)[0] = NULL; imported->imp_sid = sid; - imported->imp_flags = IMP_FLAGS_STAR; } - else - { - int i; - - arg = arg_start; - if (*arg == '{') - arg = skipwhite(arg + 1); - for (i = 0; i < names.ga_len; ++i) - { - char_u *name = ((char_u **)names.ga_data)[i]; - char_u *as_name = ((char_u **)as_names.ga_data)[i]; - size_t len = STRLEN(name); - int idx; - imported_T *imported; - ufunc_T *ufunc = NULL; - type_T *type; - idx = find_exported(sid, name, &ufunc, &type, cctx, TRUE); - - if (idx < 0 && ufunc == NULL) - goto erret; - - // If already imported with the same properties and the - // IMP_FLAGS_RELOAD set then we keep that entry. Otherwise create - // a new one (and give an error for an existing import). - imported = find_imported(name, len, cctx); - if (imported != NULL - && (imported->imp_flags & IMP_FLAGS_RELOAD) - && imported->imp_sid == sid - && (idx >= 0 - ? (equal_type(imported->imp_type, type, 0) - && imported->imp_var_vals_idx == idx) - : (equal_type(imported->imp_type, ufunc->uf_func_type, - ETYPE_ARG_UNKNOWN) - && STRCMP(imported->imp_funcname, - ufunc->uf_name) == 0))) - { - imported->imp_flags &= ~IMP_FLAGS_RELOAD; - } - else - { - if (as_name == NULL - && check_defined(name, len, cctx, FALSE) == FAIL) - goto erret; - - imported = new_imported(gap != NULL ? gap - : &SCRIPT_ITEM(import_sid)->sn_imports); - if (imported == NULL) - goto erret; - - if (as_name == NULL) - { - imported->imp_name = name; - ((char_u **)names.ga_data)[i] = NULL; - } - else - { - // "import This as That ..." - imported->imp_name = as_name; - ((char_u **)as_names.ga_data)[i] = NULL; - } - imported->imp_sid = sid; - if (idx >= 0) - { - imported->imp_type = type; - imported->imp_var_vals_idx = idx; - } - else - { - imported->imp_type = ufunc->uf_func_type; - imported->imp_funcname = ufunc->uf_name; - } - } - } - } erret: clear_tv(&tv); ! ga_clear_strings(&names); ! ga_clear_strings(&as_names); ! return cmd_end; } /* ! * ":import Item from 'filename'" ! * ":import Item as Alias from 'filename'" ! * ":import {Item} from 'filename'". ! * ":import {Item as Alias} from 'filename'" ! * ":import {Item, Item} from 'filename'" ! * ":import {Item, Item as Alias} from 'filename'" ! * ! * ":import * as Name from 'filename'" */ void ex_import(exarg_T *eap) --- 499,525 ---- goto erret; } } + else if (check_defined(as_name, STRLEN(as_name), cctx, FALSE) == FAIL) + goto erret; imported = new_imported(gap != NULL ? gap : &SCRIPT_ITEM(import_sid)->sn_imports); if (imported == NULL) goto erret; imported->imp_name = as_name; ! as_name = NULL; imported->imp_sid = sid; } erret: clear_tv(&tv); ! vim_free(as_name); ! return arg; } /* ! * ":import 'filename'" ! * ":import 'filename' as Name" */ void ex_import(exarg_T *eap) *************** *** 673,679 **** } /* ! * Find an exported item in "sid" matching the name at "*argp". * When it is a variable return the index. * When it is a user function return "*ufunc". * When not found returns -1 and "*ufunc" is NULL. --- 542,548 ---- } /* ! * Find an exported item in "sid" matching "name". * When it is a variable return the index. * When it is a user function return "*ufunc". * When not found returns -1 and "*ufunc" is NULL. *************** *** 807,813 **** init_tv.v_type = VAR_NUMBER; else init_tv.v_type = type->tt_type; ! set_var_const(name, type, &init_tv, FALSE, 0, 0); vim_free(name); return p; --- 676,682 ---- init_tv.v_type = VAR_NUMBER; else init_tv.v_type = type->tt_type; ! set_var_const(name, 0, type, &init_tv, FALSE, 0, 0); vim_free(name); return p; *************** *** 902,908 **** } else { ! sv = find_typval_in_script(&di->di_tv); } if (sv != NULL) { --- 771,777 ---- } else { ! sv = find_typval_in_script(&di->di_tv, 0); } if (sv != NULL) { *************** *** 991,1002 **** /* * Find the script-local variable that links to "dest". * Returns NULL if not found and give an internal error. */ svar_T * ! find_typval_in_script(typval_T *dest) { ! scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); int idx; if (si->sn_version != SCRIPT_VERSION_VIM9) --- 860,872 ---- /* * Find the script-local variable that links to "dest". + * If "sid" is zero use the current script. * Returns NULL if not found and give an internal error. */ svar_T * ! find_typval_in_script(typval_T *dest, scid_T sid) { ! scriptitem_T *si = SCRIPT_ITEM(sid == 0 ? current_sctx.sc_sid : sid); int idx; if (si->sn_version != SCRIPT_VERSION_VIM9) *** ../vim-8.2.4018/src/proto/vim9script.pro 2021-11-26 17:36:48.008799188 +0000 --- src/proto/vim9script.pro 2022-01-06 19:23:37.616651058 +0000 *************** *** 15,21 **** char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg); void update_vim9_script_var(int create, dictitem_T *di, int flags, typval_T *tv, type_T **type, int do_member); void hide_script_var(scriptitem_T *si, int idx, int func_defined); ! svar_T *find_typval_in_script(typval_T *dest); int check_script_var_type(svar_T *sv, typval_T *value, char_u *name, where_T where); int check_reserved_name(char_u *name); /* vim: set ft=c : */ --- 15,21 ---- char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg); void update_vim9_script_var(int create, dictitem_T *di, int flags, typval_T *tv, type_T **type, int do_member); void hide_script_var(scriptitem_T *si, int idx, int func_defined); ! svar_T *find_typval_in_script(typval_T *dest, scid_T sid); int check_script_var_type(svar_T *sv, typval_T *value, char_u *name, where_T where); int check_reserved_name(char_u *name); /* vim: set ft=c : */ *** ../vim-8.2.4018/src/errors.h 2022-01-06 11:43:12.913089957 +0000 --- src/errors.h 2022-01-06 17:22:26.117706580 +0000 *************** *** 2500,2507 **** INIT(= N_("E1069: White space required after '%s': %s")); EXTERN char e_missing_from[] INIT(= N_("E1070: Missing \"from\"")); ! EXTERN char e_invalid_string_after_from[] ! INIT(= N_("E1071: Invalid string after \"from\"")); EXTERN char e_cannot_compare_str_with_str[] INIT(= N_("E1072: Cannot compare %s with %s")); EXTERN char e_name_already_defined_str[] --- 2500,2507 ---- INIT(= N_("E1069: White space required after '%s': %s")); EXTERN char e_missing_from[] INIT(= N_("E1070: Missing \"from\"")); ! EXTERN char e_invalid_string_for_import_str[] ! INIT(= N_("E1071: Invalid string for :import: %s")); EXTERN char e_cannot_compare_str_with_str[] INIT(= N_("E1072: Cannot compare %s with %s")); EXTERN char e_name_already_defined_str[] *************** *** 2839,2846 **** INIT(= N_("E1234: legacy must be followed by a command")); EXTERN char e_function_reference_is_not_set[] INIT(= N_("E1235: Function reference is not set")); ! EXTERN char e_cannot_use_str_itself_it_is_imported_with_star[] ! INIT(= N_("E1236: Cannot use %s itself, it is imported with '*'")); EXTERN char e_no_such_user_defined_command_in_current_buffer_str[] INIT(= N_("E1237: No such user-defined command in current buffer: %s")); EXTERN char e_blob_required_for_argument_nr[] --- 2839,2846 ---- INIT(= N_("E1234: legacy must be followed by a command")); EXTERN char e_function_reference_is_not_set[] INIT(= N_("E1235: Function reference is not set")); ! EXTERN char e_cannot_use_str_itself_it_is_imported[] ! INIT(= N_("E1236: Cannot use %s itself, it is imported")); EXTERN char e_no_such_user_defined_command_in_current_buffer_str[] INIT(= N_("E1237: No such user-defined command in current buffer: %s")); EXTERN char e_blob_required_for_argument_nr[] *************** *** 2881,2883 **** --- 2881,2891 ---- INIT(= N_("E1255: mapping must end with ")); EXTERN char e_string_or_function_required_for_argument_nr[] INIT(= N_("E1256: String or function required for argument %d")); + EXTERN char e_imported_script_must_end_in_dot_vim_str[] + INIT(= N_("E1257: Imported script must end in .vim: %s")); + EXTERN char e_no_dot_after_imported_name_str[] + INIT(= N_("E1258: No '.' after imported name: %s")); + EXTERN char e_missing_name_after_imported_name_str[] + INIT(= N_("E1259: Missing name after imported name: %s")); + EXTERN char e_cannot_unlet_imported_item_str[] + INIT(= N_("E1260: Cannot unlet an imported item: %s")); *** ../vim-8.2.4018/src/structs.h 2022-01-06 13:24:45.789265688 +0000 --- src/structs.h 2022-01-06 18:54:10.296695529 +0000 *************** *** 1822,1840 **** typedef struct { char_u *imp_name; // name imported as (allocated) ! int imp_sid; // script ID of "from" ! int imp_flags; // IMP_FLAGS_ values - - // for a variable - type_T *imp_type; - int imp_var_vals_idx; // index in sn_var_vals of "from" - - // for a function - char_u *imp_funcname; // user func name (NOT allocated) } imported_T; - #define IMP_FLAGS_STAR 1 // using "import * as Name" #define IMP_FLAGS_RELOAD 2 // script reloaded, OK to redefine /* --- 1822,1831 ---- typedef struct { char_u *imp_name; // name imported as (allocated) ! scid_T imp_sid; // script ID of "from" int imp_flags; // IMP_FLAGS_ values } imported_T; #define IMP_FLAGS_RELOAD 2 // script reloaded, OK to redefine /* *************** *** 4264,4269 **** --- 4255,4264 ---- char_u *ll_name_end; // end of variable name (can be NULL) type_T *ll_type; // type of variable (can be NULL) char_u *ll_exp_name; // NULL or expanded name in allocated memory. + + scid_T ll_sid; // for an imported item: the script ID it was + // imported from; zero otherwise + typval_T *ll_tv; // Typeval of item being used. If "newkey" // isn't NULL it's the Dict to which to add // the item. *** ../vim-8.2.4018/src/eval.c 2022-01-05 10:16:27.172425489 +0000 --- src/eval.c 2022-01-06 20:12:11.039889235 +0000 *************** *** 56,62 **** static int free_unref_items(int copyID); static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end); - static char_u *eval_next_line(evalarg_T *evalarg); /* * Return "n1" divided by "n2", taking care of dividing by zero. --- 56,61 ---- *************** *** 922,930 **** } } } // Without [idx] or .key we are done. ! if ((*p != '[' && *p != '.') || lp->ll_name == NULL) return p; if (in_vim9script() && lval_root != NULL) --- 921,957 ---- } } } + if (lp->ll_name == NULL) + return p; + + if (*p == '.' && in_vim9script()) + { + imported_T *import = find_imported(lp->ll_name, p - lp->ll_name, NULL); + if (import != NULL) + { + ufunc_T *ufunc; + type_T *type; + + lp->ll_sid = import->imp_sid; + lp->ll_name = skipwhite(p + 1); + p = find_name_end(lp->ll_name, NULL, NULL, fne_flags); + lp->ll_name_end = p; + + // check the item is exported + cc = *p; + *p = NUL; + if (find_exported(import->imp_sid, lp->ll_name, &ufunc, &type, + NULL, TRUE) == -1) + { + *p = cc; + return FAIL; + } + *p = cc; + } + } // Without [idx] or .key we are done. ! if ((*p != '[' && *p != '.')) return p; if (in_vim9script() && lval_root != NULL) *************** *** 997,1003 **** && lp->ll_tv == &v->di_tv && ht != NULL && ht == get_script_local_ht()) { ! svar_T *sv = find_typval_in_script(lp->ll_tv); // Vim9 script local variable: get the type if (sv != NULL) --- 1024,1030 ---- && lp->ll_tv == &v->di_tv && ht != NULL && ht == get_script_local_ht()) { ! svar_T *sv = find_typval_in_script(lp->ll_tv, 0); // Vim9 script local variable: get the type if (sv != NULL) *************** *** 1359,1371 **** // handle +=, -=, *=, /=, %= and .= di = NULL; if (eval_variable(lp->ll_name, (int)STRLEN(lp->ll_name), ! &tv, &di, EVAL_VAR_VERBOSE) == OK) { if ((di == NULL || (!var_check_ro(di->di_flags, lp->ll_name, FALSE) && !tv_check_lock(&di->di_tv, lp->ll_name, FALSE))) && tv_op(&tv, rettv, op) == OK) ! set_var_const(lp->ll_name, NULL, &tv, FALSE, ASSIGN_NO_DECL, 0); clear_tv(&tv); } --- 1386,1398 ---- // handle +=, -=, *=, /=, %= and .= di = NULL; if (eval_variable(lp->ll_name, (int)STRLEN(lp->ll_name), ! lp->ll_sid, &tv, &di, EVAL_VAR_VERBOSE) == OK) { if ((di == NULL || (!var_check_ro(di->di_flags, lp->ll_name, FALSE) && !tv_check_lock(&di->di_tv, lp->ll_name, FALSE))) && tv_op(&tv, rettv, op) == OK) ! set_var_const(lp->ll_name, lp->ll_sid, NULL, &tv, FALSE, ASSIGN_NO_DECL, 0); clear_tv(&tv); } *************** *** 1375,1381 **** if (lp->ll_type != NULL && check_typval_arg_type(lp->ll_type, rettv, NULL, 0) == FAIL) return; ! set_var_const(lp->ll_name, lp->ll_type, rettv, copy, flags, var_idx); } *endp = cc; --- 1402,1408 ---- if (lp->ll_type != NULL && check_typval_arg_type(lp->ll_type, rettv, NULL, 0) == FAIL) return; ! set_var_const(lp->ll_name, lp->ll_sid, lp->ll_type, rettv, copy, flags, var_idx); } *endp = cc; *************** *** 1389,1395 **** if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) && (flags & ASSIGN_FOR_LOOP) == 0) { ! emsg(_("E996: Cannot lock a range")); return; } --- 1416,1422 ---- if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) && (flags & ASSIGN_FOR_LOOP) == 0) { ! emsg(_(e_cannot_lock_range)); return; } *************** *** 1404,1410 **** if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) && (flags & ASSIGN_FOR_LOOP) == 0) { ! emsg(_("E996: Cannot lock a list or dict")); return; } --- 1431,1437 ---- if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) && (flags & ASSIGN_FOR_LOOP) == 0) { ! emsg(_(e_cannot_lock_list_or_dict)); return; } *************** *** 2089,2095 **** * FALSE. * "arg" must point somewhere inside a line, not at the start. */ ! static char_u * eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext) { char_u *p = skipwhite(arg); --- 2116,2122 ---- * FALSE. * "arg" must point somewhere inside a line, not at the start. */ ! char_u * eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext) { char_u *p = skipwhite(arg); *************** *** 2120,2126 **** * To be called after eval_next_non_blank() sets "getnext" to TRUE. * Only called for Vim9 script. */ ! static char_u * eval_next_line(evalarg_T *evalarg) { garray_T *gap = &evalarg->eval_ga; --- 2147,2153 ---- * To be called after eval_next_non_blank() sets "getnext" to TRUE. * Only called for Vim9 script. */ ! char_u * eval_next_line(evalarg_T *evalarg) { garray_T *gap = &evalarg->eval_ga; *************** *** 2236,2248 **** exarg_T *eap, evalarg_T *evalarg) { int ret; char_u *p; char_u *expr_end; int did_emsg_before = did_emsg; int called_emsg_before = called_emsg; int flags = evalarg == NULL ? 0 : evalarg->eval_flags; ! int check_for_end = TRUE; int end_error = FALSE; p = skipwhite(arg); --- 2263,2290 ---- exarg_T *eap, evalarg_T *evalarg) { + return eval0_retarg(arg, rettv, eap, evalarg, NULL); + } + + /* + * Like eval0() but when "retarg" is not NULL store the pointer to after the + * expression and don't check what comes after the expression. + */ + int + eval0_retarg( + char_u *arg, + typval_T *rettv, + exarg_T *eap, + evalarg_T *evalarg, + char_u **retarg) + { int ret; char_u *p; char_u *expr_end; int did_emsg_before = did_emsg; int called_emsg_before = called_emsg; int flags = evalarg == NULL ? 0 : evalarg->eval_flags; ! int check_for_end = retarg == NULL; int end_error = FALSE; p = skipwhite(arg); *************** *** 2253,2259 **** // In Vim9 script a command block is not split at NL characters for // commands using an expression argument. Skip over a '#' comment to check // for a following NL. Require white space before the '#'. ! if (in_vim9script() && p > expr_end) while (*p == '#') { char_u *nl = vim_strchr(p, NL); --- 2295,2301 ---- // In Vim9 script a command block is not split at NL characters for // commands using an expression argument. Skip over a '#' comment to check // for a following NL. Require white space before the '#'. ! if (in_vim9script() && p > expr_end && retarg == NULL) while (*p == '#') { char_u *nl = vim_strchr(p, NL); *************** *** 2298,2304 **** return FAIL; } ! if (check_for_end && eap != NULL) set_nextcmd(eap, p); return ret; --- 2340,2348 ---- return FAIL; } ! if (retarg != NULL) ! *retarg = p; ! else if (check_for_end && eap != NULL) set_nextcmd(eap, p); return ret; *************** *** 3669,3675 **** ret = OK; } else ! ret = eval_variable(s, len, rettv, NULL, EVAL_VAR_VERBOSE + EVAL_VAR_IMPORT); } else --- 3713,3719 ---- ret = OK; } else ! ret = eval_variable(s, len, 0, rettv, NULL, EVAL_VAR_VERBOSE + EVAL_VAR_IMPORT); } else *************** *** 5887,5893 **** ufunc_T *ufunc; type_T *type; ! // Found script from "import * as {name}", script item name must // follow. if (**arg != '.') { --- 5931,5937 ---- ufunc_T *ufunc; type_T *type; ! // Found script from "import {name} as name", script item name must // follow. if (**arg != '.') { *************** *** 5934,5939 **** --- 5978,5984 ---- rettv->v_type = VAR_FUNC; rettv->vval.v_string = vim_strsave(ufunc->uf_name); } + continue; } if ((**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC *** ../vim-8.2.4018/src/proto/eval.pro 2021-12-12 16:26:35.868627601 +0000 --- src/proto/eval.pro 2022-01-06 15:19:13.811165134 +0000 *************** *** 33,42 **** --- 33,45 ---- void free_for_info(void *fi_void); void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx); int pattern_match(char_u *pat, char_u *text, int ic); + char_u *eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext); + char_u *eval_next_line(evalarg_T *evalarg); char_u *skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg); void init_evalarg(evalarg_T *evalarg); void clear_evalarg(evalarg_T *evalarg, exarg_T *eap); int eval0(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg); + int eval0_retarg(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg, char_u **retarg); int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg); void eval_addblob(typval_T *tv1, typval_T *tv2); int eval_addlist(typval_T *tv1, typval_T *tv2); *** ../vim-8.2.4018/src/evalvars.c 2022-01-06 13:24:45.789265688 +0000 --- src/evalvars.c 2022-01-06 19:25:26.908469244 +0000 *************** *** 1232,1238 **** arg = skipwhite(arg); if (tofree != NULL) name = tofree; ! if (eval_variable(name, len, &tv, NULL, EVAL_VAR_VERBOSE) == FAIL) error = TRUE; else --- 1232,1238 ---- arg = skipwhite(arg); if (tofree != NULL) name = tofree; ! if (eval_variable(name, len, 0, &tv, NULL, EVAL_VAR_VERBOSE) == FAIL) error = TRUE; else *************** *** 2645,2650 **** --- 2645,2651 ---- eval_variable( char_u *name, int len, // length of "name" + scid_T sid, // script ID for imported item or zero typval_T *rettv, // NULL when only checking existence dictitem_T **dip, // non-NULL when typval's dict item is needed int flags) // EVAL_VAR_ flags *************** *** 2678,2725 **** if (tv == NULL && (in_vim9script() || STRNCMP(name, "s:", 2) == 0)) { ! imported_T *import; char_u *p = STRNCMP(name, "s:", 2) == 0 ? name + 2 : name; ! import = find_imported(p, 0, NULL); // imported variable from another script ! if (import != NULL) { ! if (import->imp_funcname != NULL) { ! found = TRUE; ! if (rettv != NULL) { ! rettv->v_type = VAR_FUNC; ! rettv->vval.v_string = vim_strsave(import->imp_funcname); } ! } ! else if (import->imp_flags & IMP_FLAGS_STAR) ! { ! if ((flags & EVAL_VAR_IMPORT) == 0) { if (flags & EVAL_VAR_VERBOSE) emsg(_(e_import_as_name_not_supported_here)); ret = FAIL; } - else - { - if (rettv != NULL) - { - rettv->v_type = VAR_ANY; - rettv->vval.v_number = import->imp_sid; - } - found = TRUE; - } } else { ! scriptitem_T *si = SCRIPT_ITEM(import->imp_sid); ! svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) ! + import->imp_var_vals_idx; ! tv = sv->sv_tv; ! type = sv->sv_type; } } else if (in_vim9script() && (flags & EVAL_VAR_NO_FUNC) == 0) --- 2679,2728 ---- if (tv == NULL && (in_vim9script() || STRNCMP(name, "s:", 2) == 0)) { ! imported_T *import = NULL; char_u *p = STRNCMP(name, "s:", 2) == 0 ? name + 2 : name; ! if (sid == 0) ! import = find_imported(p, 0, NULL); // imported variable from another script ! if (import != NULL || sid != 0) { ! if ((flags & EVAL_VAR_IMPORT) == 0) { ! if (sid != 0 && SCRIPT_ID_VALID(sid)) { ! ht = &SCRIPT_VARS(sid); ! if (ht != NULL) ! { ! dictitem_T *v = find_var_in_ht(ht, 0, name, ! flags & EVAL_VAR_NOAUTOLOAD); ! ! if (v != NULL) ! { ! tv = &v->di_tv; ! if (dip != NULL) ! *dip = v; ! } ! else ! ht = NULL; ! } } ! else { if (flags & EVAL_VAR_VERBOSE) emsg(_(e_import_as_name_not_supported_here)); ret = FAIL; } } else { ! if (rettv != NULL) ! { ! rettv->v_type = VAR_ANY; ! rettv->vval.v_number = sid != 0 ? sid : import->imp_sid; ! } ! found = TRUE; } } else if (in_vim9script() && (flags & EVAL_VAR_NO_FUNC) == 0) *************** *** 2760,2766 **** if (ht != NULL && ht == get_script_local_ht() && tv != &SCRIPT_SV(current_sctx.sc_sid)->sv_var.di_tv) { ! svar_T *sv = find_typval_in_script(tv); if (sv != NULL) type = sv->sv_type; --- 2763,2769 ---- if (ht != NULL && ht == get_script_local_ht() && tv != &SCRIPT_SV(current_sctx.sc_sid)->sv_var.di_tv) { ! svar_T *sv = find_typval_in_script(tv, 0); if (sv != NULL) type = sv->sv_type; *************** *** 3278,3294 **** typval_T *tv, int copy) // make copy of value in "tv" { ! set_var_const(name, NULL, tv, copy, ASSIGN_DECL, 0); } /* * Set variable "name" to value in "tv". * If the variable already exists and "is_const" is FALSE the value is updated. * Otherwise the variable is created. */ void set_var_const( char_u *name, type_T *type_arg, typval_T *tv_arg, int copy, // make copy of value in "tv" --- 3281,3299 ---- typval_T *tv, int copy) // make copy of value in "tv" { ! set_var_const(name, 0, NULL, tv, copy, ASSIGN_DECL, 0); } /* * Set variable "name" to value in "tv". + * When "sid" is non-zero "name" is in the script with this ID. * If the variable already exists and "is_const" is FALSE the value is updated. * Otherwise the variable is created. */ void set_var_const( char_u *name, + scid_T sid, type_T *type_arg, typval_T *tv_arg, int copy, // make copy of value in "tv" *************** *** 3301,3320 **** dictitem_T *di; typval_T *dest_tv = NULL; char_u *varname; ! hashtab_T *ht; int is_script_local; int vim9script = in_vim9script(); int var_in_vim9script; int flags = flags_arg; int free_tv_arg = !copy; // free tv_arg if not used ! ht = find_var_ht(name, &varname); if (ht == NULL || *varname == NUL) { semsg(_(e_illegal_variable_name_str), name); goto failed; } ! is_script_local = ht == get_script_local_ht(); if (vim9script && !is_script_local --- 3306,3332 ---- dictitem_T *di; typval_T *dest_tv = NULL; char_u *varname; ! hashtab_T *ht = NULL; int is_script_local; int vim9script = in_vim9script(); int var_in_vim9script; int flags = flags_arg; int free_tv_arg = !copy; // free tv_arg if not used ! if (sid != 0) ! { ! if (SCRIPT_ID_VALID(sid)) ! ht = &SCRIPT_VARS(sid); ! varname = name; ! } ! else ! ht = find_var_ht(name, &varname); if (ht == NULL || *varname == NUL) { semsg(_(e_illegal_variable_name_str), name); goto failed; } ! is_script_local = ht == get_script_local_ht() || sid != 0; if (vim9script && !is_script_local *************** *** 3347,3379 **** if (import != NULL) { ! scriptitem_T *si = SCRIPT_ITEM(import->imp_sid); ! svar_T *sv; ! where_T where = WHERE_INIT; ! ! // imported variable from another script if ((flags & ASSIGN_NO_DECL) == 0) { semsg(_(e_redefining_imported_item_str), name); goto failed; } ! if (import->imp_flags & IMP_FLAGS_STAR) ! { ! semsg(_(e_cannot_use_str_itself_it_is_imported_with_star), ! name); ! goto failed; ! } ! sv = ((svar_T *)si->sn_var_vals.ga_data) + import->imp_var_vals_idx; ! ! where.wt_variable = TRUE; ! if (check_typval_type(sv->sv_type, tv, where) == FAIL ! || value_check_lock(sv->sv_tv->v_lock, name, FALSE)) ! { ! goto failed; ! } ! ! dest_tv = sv->sv_tv; ! clear_tv(dest_tv); } } --- 3359,3372 ---- if (import != NULL) { ! // imported name space cannot be used if ((flags & ASSIGN_NO_DECL) == 0) { semsg(_(e_redefining_imported_item_str), name); goto failed; } ! semsg(_(e_cannot_use_str_itself_it_is_imported), name); ! goto failed; } } *************** *** 3419,3425 **** if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0) { where_T where = WHERE_INIT; ! svar_T *sv = find_typval_in_script(&di->di_tv); if (sv != NULL) { --- 3412,3418 ---- if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0) { where_T where = WHERE_INIT; ! svar_T *sv = find_typval_in_script(&di->di_tv, sid); if (sv != NULL) { *************** *** 3956,3962 **** { if (tofree != NULL) name = tofree; ! n = (eval_variable(name, len, &tv, NULL, EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT) == OK); if (n) { --- 3949,3955 ---- { if (tofree != NULL) name = tofree; ! n = (eval_variable(name, len, 0, &tv, NULL, EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT) == OK); if (n) { *** ../vim-8.2.4018/src/proto/evalvars.pro 2021-12-24 21:36:08.428028943 +0000 --- src/proto/evalvars.pro 2022-01-06 19:20:00.228995943 +0000 *************** *** 57,63 **** char_u *v_exception(char_u *oldval); char_u *v_throwpoint(char_u *oldval); char_u *set_cmdarg(exarg_T *eap, char_u *oldarg); ! int eval_variable(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int flags); void check_vars(char_u *name, int len); dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload); dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload); --- 57,63 ---- char_u *v_exception(char_u *oldval); char_u *v_throwpoint(char_u *oldval); char_u *set_cmdarg(exarg_T *eap, char_u *oldarg); ! int eval_variable(char_u *name, int len, scid_T sid, typval_T *rettv, dictitem_T **dip, int flags); void check_vars(char_u *name, int len); dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload); dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload); *************** *** 72,78 **** void vars_clear_ext(hashtab_T *ht, int free_val); void delete_var(hashtab_T *ht, hashitem_T *hi); void set_var(char_u *name, typval_T *tv, int copy); ! void set_var_const(char_u *name, type_T *type_arg, typval_T *tv_arg, int copy, int flags_arg, int var_idx); int var_check_permission(dictitem_T *di, char_u *name); int var_check_ro(int flags, char_u *name, int use_gettext); int var_check_lock(int flags, char_u *name, int use_gettext); --- 72,78 ---- void vars_clear_ext(hashtab_T *ht, int free_val); void delete_var(hashtab_T *ht, hashitem_T *hi); void set_var(char_u *name, typval_T *tv, int copy); ! void set_var_const(char_u *name, scid_T sid, type_T *type_arg, typval_T *tv_arg, int copy, int flags_arg, int var_idx); int var_check_permission(dictitem_T *di, char_u *name); int var_check_ro(int flags, char_u *name, int use_gettext); int var_check_lock(int flags, char_u *name, int use_gettext); *** ../vim-8.2.4018/src/userfunc.c 2022-01-05 20:24:34.280005633 +0000 --- src/userfunc.c 2022-01-06 19:25:36.316453384 +0000 *************** *** 1608,1641 **** } import = find_imported(p, len, NULL); ! // imported variable from another script if (import != NULL) { ! if (import->imp_funcname != NULL) ! { ! s = import->imp_funcname; ! *lenp = (int)STRLEN(s); ! return s; ! } ! if (import->imp_flags & IMP_FLAGS_STAR) ! { ! name[len] = NUL; ! semsg(_(e_cannot_use_str_itself_it_is_imported_with_star), ! name); ! name[len] = cc; ! *lenp = 0; ! return (char_u *)""; // just in case ! } ! else ! { ! scriptitem_T *si = SCRIPT_ITEM(import->imp_sid); ! svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) ! + import->imp_var_vals_idx; ! tv = sv->sv_tv; ! if (type != NULL) ! *type = sv->sv_type; ! did_type = TRUE; ! } } } --- 1608,1621 ---- } import = find_imported(p, len, NULL); ! // imported function from another script if (import != NULL) { ! name[len] = NUL; ! semsg(_(e_cannot_use_str_itself_it_is_imported), name); ! name[len] = cc; ! *lenp = 0; ! return (char_u *)""; // just in case } } *************** *** 1673,1679 **** { if (!did_type && type != NULL && ht == get_script_local_ht()) { ! svar_T *sv = find_typval_in_script(tv); if (sv != NULL) *type = sv->sv_type; --- 1653,1659 ---- { if (!did_type && type != NULL && ht == get_script_local_ht()) { ! svar_T *sv = find_typval_in_script(tv, 0); if (sv != NULL) *type = sv->sv_type; *************** *** 1905,1920 **** * Return NULL for unknown function. */ ufunc_T * ! find_func_even_dead(char_u *name, int is_global, cctx_T *cctx) { hashitem_T *hi; ufunc_T *func; - imported_T *imported; if (!is_global) { - char_u *after_script = NULL; - long sid = 0; int find_script_local = in_vim9script() && eval_isnamec1(*name) && (name[1] != ':' || *name == 's'); --- 1885,1897 ---- * Return NULL for unknown function. */ ufunc_T * ! find_func_even_dead(char_u *name, int is_global, cctx_T *cctx UNUSED) { hashitem_T *hi; ufunc_T *func; if (!is_global) { int find_script_local = in_vim9script() && eval_isnamec1(*name) && (name[1] != ':' || *name == 's'); *************** *** 1926,1960 **** if (func != NULL) return func; } - - if (name[0] == K_SPECIAL - && name[1] == KS_EXTRA - && name[2] == KE_SNR) - { - // Caller changes s: to 99_name. - - after_script = name + 3; - sid = getdigits(&after_script); - if (*after_script == '_') - ++after_script; - else - after_script = NULL; - } - if (find_script_local || after_script != NULL) - { - // Find imported function before global one. - if (after_script != NULL && sid != current_sctx.sc_sid) - imported = find_imported_in_script(after_script, 0, sid); - else - imported = find_imported(after_script == NULL - ? name : after_script, 0, cctx); - if (imported != NULL && imported->imp_funcname != NULL) - { - hi = hash_find(&func_hashtab, imported->imp_funcname); - if (!HASHITEM_EMPTY(hi)) - return HI2UF(hi); - } - } } hi = hash_find(&func_hashtab, --- 1903,1908 ---- *************** *** 4257,4264 **** // In Vim9 script a function cannot have the same name as a // variable. if (vim9script && *arg == K_SPECIAL ! && eval_variable(name_base, (int)STRLEN(name_base), NULL, NULL, ! EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT + EVAL_VAR_NO_FUNC) == OK) { semsg(_(e_redefining_script_item_str), name_base); --- 4205,4212 ---- // In Vim9 script a function cannot have the same name as a // variable. if (vim9script && *arg == K_SPECIAL ! && eval_variable(name_base, (int)STRLEN(name_base), 0, NULL, ! NULL, EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT + EVAL_VAR_NO_FUNC) == OK) { semsg(_(e_redefining_script_item_str), name_base); *** ../vim-8.2.4018/src/vim9expr.c 2022-01-04 15:16:57.883864877 +0000 --- src/vim9expr.c 2022-01-06 20:03:46.633423910 +0000 *************** *** 240,246 **** cctx_T *cctx, char_u *name, // variable NUL terminated char_u *start, // start of variable ! char_u **end, // end of variable int error) // when TRUE may give error { scriptitem_T *si; --- 240,246 ---- cctx_T *cctx, char_u *name, // variable NUL terminated char_u *start, // start of variable ! char_u **end, // end of variable, may be NULL int error) // when TRUE may give error { scriptitem_T *si; *************** *** 266,330 **** return OK; } ! import = find_imported(name, 0, cctx); if (import != NULL) { ! if (import->imp_flags & IMP_FLAGS_STAR) { ! char_u *p = skipwhite(*end); ! char_u *exp_name; ! int cc; ! ufunc_T *ufunc; ! type_T *type; ! // Used "import * as Name", need to lookup the member. ! if (*p != '.') ! { ! semsg(_(e_expected_dot_after_name_str), start); ! return FAIL; ! } ++p; ! if (VIM_ISWHITE(*p)) ! { ! emsg(_(e_no_white_space_allowed_after_dot)); ! return FAIL; ! } ! ! // isolate one name ! exp_name = p; ! while (eval_isnamec(*p)) ! ++p; ! cc = *p; ! *p = NUL; ! idx = find_exported(import->imp_sid, exp_name, &ufunc, &type, cctx, TRUE); ! *p = cc; ! p = skipwhite(p); ! *end = p; ! if (idx < 0) { ! if (*p == '(' && ufunc != NULL) ! { ! generate_PUSHFUNC(cctx, ufunc->uf_name, import->imp_type); ! return OK; ! } ! return FAIL; } ! ! generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT, ! import->imp_sid, ! idx, ! type); } ! else if (import->imp_funcname != NULL) ! generate_PUSHFUNC(cctx, import->imp_funcname, import->imp_type); ! else ! generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT, ! import->imp_sid, ! import->imp_var_vals_idx, ! import->imp_type); return OK; } --- 266,321 ---- return OK; } ! import = end == NULL ? NULL : find_imported(name, 0, cctx); if (import != NULL) { ! char_u *p = skipwhite(*end); ! char_u *exp_name; ! int cc; ! ufunc_T *ufunc; ! type_T *type; ! ! // Need to lookup the member. ! if (*p != '.') ! { ! semsg(_(e_expected_dot_after_name_str), start); ! return FAIL; ! } ! ++p; ! if (VIM_ISWHITE(*p)) { ! emsg(_(e_no_white_space_allowed_after_dot)); ! return FAIL; ! } ! // isolate one name ! exp_name = p; ! while (eval_isnamec(*p)) ++p; ! cc = *p; ! *p = NUL; ! idx = find_exported(import->imp_sid, exp_name, &ufunc, &type, cctx, TRUE); ! *p = cc; ! p = skipwhite(p); ! *end = p; ! if (idx < 0) ! { ! if (ufunc != NULL) { ! // function call or function reference ! generate_PUSHFUNC(cctx, ufunc->uf_name, NULL); ! return OK; } ! return FAIL; } ! ! generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT, ! import->imp_sid, ! idx, ! type); return OK; } *** ../vim-8.2.4018/src/vim9compile.c 2022-01-06 12:23:26.833759704 +0000 --- src/vim9compile.c 2022-01-06 17:11:23.700331750 +0000 *************** *** 1357,1363 **** --- 1357,1395 ---- // existing script-local variables should have a type lhs->lhs_scriptvar_sid = current_sctx.sc_sid; if (import != NULL) + { + char_u *dot = vim_strchr(var_start, '.'); + char_u *p; + + // for an import the name is what comes after the dot + if (dot == NULL) + { + semsg(_(e_no_dot_after_imported_name_str), + var_start); + return FAIL; + } + p = skipwhite(dot + 1); + var_end = to_name_end(p, TRUE); + if (var_end == p) + { + semsg(_(e_missing_name_after_imported_name_str), + var_start); + return FAIL; + } + vim_free(lhs->lhs_name); + lhs->lhs_varlen = var_end - p; + lhs->lhs_name = vim_strnsave(p, lhs->lhs_varlen); + if (lhs->lhs_name == NULL) + return FAIL; + rawname = lhs->lhs_name; lhs->lhs_scriptvar_sid = import->imp_sid; + // TODO: where do we check this name is exported? + + // Check if something follows: "exp.var[idx]" or + // "exp.var.key". + lhs->lhs_has_index = lhs->lhs_dest_end + > skipwhite(var_end); + } if (SCRIPT_ID_VALID(lhs->lhs_scriptvar_sid)) { // Check writable only when no index follows. *** ../vim-8.2.4018/src/vim9execute.c 2022-01-01 18:29:17.265807214 +0000 --- src/vim9execute.c 2022-01-06 19:27:01.236308936 +0000 *************** *** 1160,1166 **** if (tv->v_lock) flags |= ASSIGN_CONST; save_funccal(&entry); ! set_var_const(name, NULL, tv, FALSE, flags, 0); restore_funccal(); } --- 1160,1166 ---- if (tv->v_lock) flags |= ASSIGN_CONST; save_funccal(&entry); ! set_var_const(name, 0, NULL, tv, FALSE, flags, 0); restore_funccal(); } *************** *** 2252,2258 **** if (GA_GROW_FAILS(&ectx->ec_stack, 1)) goto theend; SOURCING_LNUM = iptr->isn_lnum; ! if (eval_variable(name, (int)STRLEN(name), STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL) goto on_error; ++ectx->ec_stack.ga_len; --- 2252,2258 ---- if (GA_GROW_FAILS(&ectx->ec_stack, 1)) goto theend; SOURCING_LNUM = iptr->isn_lnum; ! if (eval_variable(name, (int)STRLEN(name), 0, STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL) goto on_error; ++ectx->ec_stack.ga_len; *** ../vim-8.2.4018/src/testdir/test_vim9_assign.vim 2022-01-05 10:16:27.176425477 +0000 --- src/testdir/test_vim9_assign.vim 2022-01-06 17:25:25.249733177 +0000 *************** *** 2109,2121 **** writefile(['vim9script', 'export var svar = 1234'], 'XunletExport.vim') var lines =<< trim END vim9script ! import svar from './XunletExport.vim' def UnletSvar() ! unlet svar enddef defcompile END ! CheckScriptFailure(lines, 'E1081:', 1) delete('XunletExport.vim') $ENVVAR = 'foobar' --- 2109,2121 ---- writefile(['vim9script', 'export var svar = 1234'], 'XunletExport.vim') var lines =<< trim END vim9script ! import './XunletExport.vim' as exp def UnletSvar() ! unlet exp.svar enddef defcompile END ! CheckScriptFailure(lines, 'E1260:', 1) delete('XunletExport.vim') $ENVVAR = 'foobar' *** ../vim-8.2.4018/src/testdir/test_vim9_script.vim 2022-01-01 12:16:56.440066967 +0000 --- src/testdir/test_vim9_script.vim 2022-01-06 21:06:40.201452644 +0000 *************** *** 1172,1218 **** enddef def Test_vim9_import_export() var import_script_lines =<< trim END vim9script ! import {exported, Exported, ExportedValue} from './Xexport.vim' ! g:exported1 = exported ! exported += 3 ! g:exported2 = exported ! g:exported3 = ExportedValue() ! ! import ExportedInc from './Xexport.vim' ! ExportedInc() ! g:exported_i1 = exported ! g:exported_i2 = ExportedValue() ! exported = 11 ! g:exported_s1 = exported ! g:exported_s2 = ExportedValue() ! g:imported_func = Exported() def GetExported(): string ! var local_dict = {ref: Exported} return local_dict.ref() enddef g:funcref_result = GetExported() ! var dir = './' ! var ext = ".vim" ! import {exp_name} from dir .. 'Xexport' .. ext ! g:imported_name = exp_name ! exp_name ..= ' Doe' ! g:imported_name_appended = exp_name ! g:exported_later = exported ! ! import theList from './Xexport.vim' ! theList->add(2) ! assert_equal([1, 2], theList) ! END writefile(import_script_lines, 'Ximport.vim') - writefile(s:export_script_lines, 'Xexport.vim') - source Ximport.vim assert_equal('bobbie', g:result) --- 1172,1214 ---- enddef def Test_vim9_import_export() + writefile(s:export_script_lines, 'Xexport.vim') var import_script_lines =<< trim END vim9script ! var dir = './' ! var ext = ".vim" ! import dir .. 'Xexport' .. ext as expo ! g:exported1 = expo.exported ! expo.exported += 3 ! g:exported2 = expo.exported ! g:exported3 = expo.ExportedValue() ! ! expo.ExportedInc() ! g:exported_i1 = expo.exported ! g:exported_i2 = expo.ExportedValue() ! ! expo.exported = 11 ! g:exported_s1 = expo.exported ! g:exported_s2 = expo.ExportedValue() ! g:imported_func = expo.Exported() def GetExported(): string ! var local_dict = {ref: expo.Exported} return local_dict.ref() enddef g:funcref_result = GetExported() ! g:imported_name = expo.exp_name ! expo.exp_name ..= ' Doe' ! g:imported_name_appended = expo.exp_name ! g:exported_later = expo.exported + expo.theList->add(2) + assert_equal([1, 2], expo.theList) + END writefile(import_script_lines, 'Ximport.vim') source Ximport.vim assert_equal('bobbie', g:result) *************** *** 1248,1263 **** # similar, with line breaks var import_line_break_script_lines =<< trim END vim9script ! import { ! exported, ! Exported, ! } ! from ! './Xexport.vim' ! g:exported = exported ! exported += 7 ! g:exported_added = exported ! g:imported_func = Exported() END writefile(import_line_break_script_lines, 'Ximport_lbr.vim') source Ximport_lbr.vim --- 1244,1255 ---- # similar, with line breaks var import_line_break_script_lines =<< trim END vim9script ! import './Xexport.vim' ! as expo ! g:exported = expo.exported ! expo.exported += 7 ! g:exported_added = expo.exported ! g:imported_func = expo.Exported() END writefile(import_line_break_script_lines, 'Ximport_lbr.vim') source Ximport_lbr.vim *************** *** 1275,1281 **** var import_star_as_lines =<< trim END vim9script ! import * as Export from './Xexport.vim' def UseExport() g:exported_def = Export.exported enddef --- 1267,1273 ---- var import_star_as_lines =<< trim END vim9script ! import './Xexport.vim' as Export def UseExport() g:exported_def = Export.exported enddef *************** *** 1294,1300 **** var import_star_as_lines_no_dot =<< trim END vim9script ! import * as Export from './Xexport.vim' def Func() var dummy = 1 var imported = Export + dummy --- 1286,1292 ---- var import_star_as_lines_no_dot =<< trim END vim9script ! import './Xexport.vim' as Export def Func() var dummy = 1 var imported = Export + dummy *************** *** 1306,1312 **** var import_star_as_lines_dot_space =<< trim END vim9script ! import * as Export from './Xexport.vim' def Func() var imported = Export . exported enddef --- 1298,1304 ---- var import_star_as_lines_dot_space =<< trim END vim9script ! import './Xexport.vim' as Export def Func() var imported = Export . exported enddef *************** *** 1317,1324 **** var import_func_duplicated =<< trim END vim9script ! import ExportedInc from './Xexport.vim' ! import ExportedInc from './Xexport.vim' ExportedInc() END --- 1309,1316 ---- var import_func_duplicated =<< trim END vim9script ! import './Xexport.vim' as expo ! import './Xexport.vim' as expo ExportedInc() END *************** *** 1327,1335 **** var import_star_as_duplicated =<< trim END vim9script ! import * as Export from './Xexport.vim' var some = 'other' ! import * as Export from './Xexport.vim' defcompile END writefile(import_star_as_duplicated, 'Ximport.vim') --- 1319,1327 ---- var import_star_as_duplicated =<< trim END vim9script ! import './Xexport.vim' as Export var some = 'other' ! import './Xexport.vim' as Export defcompile END writefile(import_star_as_duplicated, 'Ximport.vim') *************** *** 1337,1343 **** var import_star_as_lines_script_no_dot =<< trim END vim9script ! import * as Export from './Xexport.vim' g:imported_script = Export exported END writefile(import_star_as_lines_script_no_dot, 'Ximport.vim') --- 1329,1335 ---- var import_star_as_lines_script_no_dot =<< trim END vim9script ! import './Xexport.vim' as Export g:imported_script = Export exported END writefile(import_star_as_lines_script_no_dot, 'Ximport.vim') *************** *** 1345,1351 **** var import_star_as_lines_script_space_after_dot =<< trim END vim9script ! import * as Export from './Xexport.vim' g:imported_script = Export. exported END writefile(import_star_as_lines_script_space_after_dot, 'Ximport.vim') --- 1337,1343 ---- var import_star_as_lines_script_space_after_dot =<< trim END vim9script ! import './Xexport.vim' as Export g:imported_script = Export. exported END writefile(import_star_as_lines_script_space_after_dot, 'Ximport.vim') *************** *** 1353,1359 **** var import_star_as_lines_missing_name =<< trim END vim9script ! import * as Export from './Xexport.vim' def Func() var imported = Export. enddef --- 1345,1351 ---- var import_star_as_lines_missing_name =<< trim END vim9script ! import './Xexport.vim' as Export def Func() var imported = Export. enddef *************** *** 1364,1373 **** var import_star_as_lbr_lines =<< trim END vim9script ! import * as Export - from - './Xexport.vim' def UseExport() g:exported = Export.exported enddef --- 1356,1363 ---- var import_star_as_lbr_lines =<< trim END vim9script ! import './Xexport.vim' as Export def UseExport() g:exported = Export.exported enddef *************** *** 1378,1421 **** assert_equal(18, g:exported) unlet g:exported ! var import_star_lines =<< trim END ! vim9script ! import * from './Xexport.vim' ! END ! writefile(import_star_lines, 'Ximport.vim') ! assert_fails('source Ximport.vim', 'E1045:', '', 2, 'Ximport.vim') ! ! # try to import something that exists but is not exported var import_not_exported_lines =<< trim END vim9script ! import name from './Xexport.vim' END writefile(import_not_exported_lines, 'Ximport.vim') ! assert_fails('source Ximport.vim', 'E1049:', '', 2, 'Ximport.vim') # try to import something that is already defined var import_already_defined =<< trim END vim9script var exported = 'something' ! import exported from './Xexport.vim' ! END ! writefile(import_already_defined, 'Ximport.vim') ! assert_fails('source Ximport.vim', 'E1054:', '', 3, 'Ximport.vim') ! ! # try to import something that is already defined ! import_already_defined =<< trim END ! vim9script ! var exported = 'something' ! import * as exported from './Xexport.vim' ! END ! writefile(import_already_defined, 'Ximport.vim') ! assert_fails('source Ximport.vim', 'E1054:', '', 3, 'Ximport.vim') ! ! # try to import something that is already defined ! import_already_defined =<< trim END ! vim9script ! var exported = 'something' ! import {exported} from './Xexport.vim' END writefile(import_already_defined, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1054:', '', 3, 'Ximport.vim') --- 1368,1387 ---- assert_equal(18, g:exported) unlet g:exported ! # try to use something that exists but is not exported var import_not_exported_lines =<< trim END vim9script ! import './Xexport.vim' as expo ! echo expo.name END writefile(import_not_exported_lines, 'Ximport.vim') ! assert_fails('source Ximport.vim', 'E1049:', '', 3, 'Ximport.vim') # try to import something that is already defined var import_already_defined =<< trim END vim9script var exported = 'something' ! import './Xexport.vim' as exported END writefile(import_already_defined, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1054:', '', 3, 'Ximport.vim') *************** *** 1423,1431 **** # try changing an imported const var import_assign_to_const =<< trim END vim9script ! import CONST from './Xexport.vim' def Assign() ! CONST = 987 enddef defcompile END --- 1389,1397 ---- # try changing an imported const var import_assign_to_const =<< trim END vim9script ! import './Xexport.vim' as expo def Assign() ! expo.CONST = 987 enddef defcompile END *************** *** 1435,1488 **** # try changing an imported final var import_assign_to_final =<< trim END vim9script ! import theList from './Xexport.vim' def Assign() ! theList = [2] enddef defcompile END writefile(import_assign_to_final, 'Ximport.vim') assert_fails('source Ximport.vim', 'E46:', '', 1, '_Assign') ! # import a very long name, requires making a copy ! var import_long_name_lines =<< trim END vim9script ! import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim' END ! writefile(import_long_name_lines, 'Ximport.vim') ! assert_fails('source Ximport.vim', 'E1048:', '', 2, 'Ximport.vim') ! ! var import_no_from_lines =<< trim END ! vim9script ! import name './Xexport.vim' ! END ! writefile(import_no_from_lines, 'Ximport.vim') ! assert_fails('source Ximport.vim', 'E1070:', '', 2, 'Ximport.vim') var import_invalid_string_lines =<< trim END vim9script ! import name from Xexport.vim END writefile(import_invalid_string_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E121:', '', 2, 'Ximport.vim') var import_wrong_name_lines =<< trim END vim9script ! import name from './XnoExport.vim' END writefile(import_wrong_name_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1053:', '', 2, 'Ximport.vim') - var import_missing_comma_lines =<< trim END - vim9script - import {exported name} from './Xexport.vim' - END - writefile(import_missing_comma_lines, 'Ximport3.vim') - assert_fails('source Ximport3.vim', 'E1046:', '', 2, 'Ximport3.vim') - var import_redefining_lines =<< trim END vim9script ! import exported from './Xexport.vim' var exported = 5 END writefile(import_redefining_lines, 'Ximport.vim') --- 1401,1439 ---- # try changing an imported final var import_assign_to_final =<< trim END vim9script ! import './Xexport.vim' as expo def Assign() ! expo.theList = [2] enddef defcompile END writefile(import_assign_to_final, 'Ximport.vim') assert_fails('source Ximport.vim', 'E46:', '', 1, '_Assign') ! var import_no_as_lines =<< trim END vim9script ! import './Xexport.vim' name END ! writefile(import_no_as_lines, 'Ximport.vim') ! assert_fails('source Ximport.vim', 'E488:', '', 2, 'Ximport.vim') var import_invalid_string_lines =<< trim END vim9script ! import Xexport.vim END writefile(import_invalid_string_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E121:', '', 2, 'Ximport.vim') var import_wrong_name_lines =<< trim END vim9script ! import './XnoExport.vim' END writefile(import_wrong_name_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1053:', '', 2, 'Ximport.vim') var import_redefining_lines =<< trim END vim9script ! import './Xexport.vim' as exported var exported = 5 END writefile(import_redefining_lines, 'Ximport.vim') *************** *** 1490,1508 **** var import_assign_wrong_type_lines =<< trim END vim9script ! import exported from './Xexport.vim' ! exported = 'xxx' END writefile(import_assign_wrong_type_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1012: Type mismatch; expected number but got string', '', 3) var import_assign_const_lines =<< trim END vim9script ! import CONST from './Xexport.vim' ! CONST = 4321 END writefile(import_assign_const_lines, 'Ximport.vim') ! assert_fails('source Ximport.vim', 'E741: Value is locked: CONST', '', 3) delete('Ximport.vim') delete('Ximport3.vim') --- 1441,1459 ---- var import_assign_wrong_type_lines =<< trim END vim9script ! import './Xexport.vim' as expo ! expo.exported = 'xxx' END writefile(import_assign_wrong_type_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1012: Type mismatch; expected number but got string', '', 3) var import_assign_const_lines =<< trim END vim9script ! import './Xexport.vim' as expo ! expo.CONST = 4321 END writefile(import_assign_const_lines, 'Ximport.vim') ! assert_fails('source Ximport.vim', 'E46: Cannot change read-only variable "CONST"', '', 3) delete('Ximport.vim') delete('Ximport3.vim') *************** *** 1541,1552 **** lines =<< trim END vim9script ! import {G} from './Xlib.vim' ! const Foo = G() assert_equal(42, Foo) def DoTest() ! const Goo = G() assert_equal(42, Goo) enddef DoTest() --- 1492,1503 ---- lines =<< trim END vim9script ! import './Xlib.vim' as lib ! const Foo = lib.G() assert_equal(42, Foo) def DoTest() ! const Goo = lib.G() assert_equal(42, Goo) enddef DoTest() *************** *** 1559,1588 **** def Test_import_star_fails() writefile([], 'Xfoo.vim') var lines =<< trim END ! import * as foo from './Xfoo.vim' foo = 'bar' END CheckDefAndScriptFailure(lines, ['E1094:', 'E1236: Cannot use foo itself']) lines =<< trim END vim9script ! import * as foo from './Xfoo.vim' var that = foo END CheckScriptFailure(lines, 'E1029: Expected ''.''') lines =<< trim END vim9script ! import * as 9foo from './Xfoo.vim' END CheckScriptFailure(lines, 'E1047:') lines =<< trim END vim9script ! import * as the#foo from './Xfoo.vim' END CheckScriptFailure(lines, 'E1047:') lines =<< trim END vim9script ! import * as g:foo from './Xfoo.vim' END CheckScriptFailure(lines, 'E1047:') --- 1510,1539 ---- def Test_import_star_fails() writefile([], 'Xfoo.vim') var lines =<< trim END ! import './Xfoo.vim' as foo foo = 'bar' END CheckDefAndScriptFailure(lines, ['E1094:', 'E1236: Cannot use foo itself']) lines =<< trim END vim9script ! import './Xfoo.vim' as foo var that = foo END CheckScriptFailure(lines, 'E1029: Expected ''.''') lines =<< trim END vim9script ! import './Xfoo.vim' as 9foo END CheckScriptFailure(lines, 'E1047:') lines =<< trim END vim9script ! import './Xfoo.vim' as the#foo END CheckScriptFailure(lines, 'E1047:') lines =<< trim END vim9script ! import './Xfoo.vim' as g:foo END CheckScriptFailure(lines, 'E1047:') *************** *** 1597,1649 **** END writefile([], 'Xthat.vim') lines =<< trim END ! import * as That from './Xthat.vim' That() END CheckDefAndScriptFailure(lines, ['E1094:', 'E1236: Cannot use That itself']) delete('Xthat.vim') enddef - def Test_import_as() - var export_lines =<< trim END - vim9script - export var one = 1 - export var yes = 'yes' - export var slist: list - END - writefile(export_lines, 'XexportAs') - - var import_lines =<< trim END - vim9script - var one = 'notused' - var yes = 777 - import one as thatOne from './XexportAs' - assert_equal(1, thatOne) - import yes as yesYes from './XexportAs' - assert_equal('yes', yesYes) - END - CheckScriptSuccess(import_lines) - - import_lines =<< trim END - vim9script - import {one as thatOne, yes as yesYes} from './XexportAs' - assert_equal(1, thatOne) - assert_equal('yes', yesYes) - assert_fails('echo one', 'E121:') - assert_fails('echo yes', 'E121:') - END - CheckScriptSuccess(import_lines) - - import_lines =<< trim END - vim9script - import {slist as impSlist} from './XexportAs' - impSlist->add(123) - END - CheckScriptFailure(import_lines, 'E1012: Type mismatch; expected string but got number') - - delete('XexportAs') - enddef - func g:Trigger() source Ximport.vim return "echo 'yes'\" --- 1548,1560 ---- END writefile([], 'Xthat.vim') lines =<< trim END ! import './Xthat.vim' as That That() END CheckDefAndScriptFailure(lines, ['E1094:', 'E1236: Cannot use That itself']) delete('Xthat.vim') enddef func g:Trigger() source Ximport.vim return "echo 'yes'\" *************** *** 1661,1668 **** var import_lines =<< trim END vim9script ! import That from './Xexport_that.vim' ! assert_equal('yes', That()) END writefile(import_lines, 'Ximport.vim') --- 1572,1579 ---- var import_lines =<< trim END vim9script ! import './Xexport_that.vim' as that ! assert_equal('yes', that.That()) END writefile(import_lines, 'Ximport.vim') *************** *** 1685,1692 **** var import_lines =<< trim END vim9script ! import That from './Xexport_ft.vim' ! assert_equal('yes', That) g:did_load_mytpe = 1 END writefile(import_lines, 'ftplugin/qf.vim') --- 1596,1603 ---- var import_lines =<< trim END vim9script ! import './Xexport_ft.vim' as ft ! assert_equal('yes', ft.That) g:did_load_mytpe = 1 END writefile(import_lines, 'ftplugin/qf.vim') *************** *** 1704,1733 **** &rtp = save_rtp enddef ! def Test_use_import_in_mapping() ! var lines =<< trim END ! vim9script ! export def Funcx() ! g:result = 42 ! enddef ! END ! writefile(lines, 'XsomeExport.vim') ! lines =<< trim END ! vim9script ! import Funcx from './XsomeExport.vim' ! nnoremap :call Funcx() ! END ! writefile(lines, 'Xmapscript.vim') ! ! source Xmapscript.vim ! feedkeys("\", "xt") ! assert_equal(42, g:result) ! ! unlet g:result ! delete('XsomeExport.vim') ! delete('Xmapscript.vim') ! nunmap ! enddef def Test_vim9script_mix() var lines =<< trim END --- 1615,1646 ---- &rtp = save_rtp enddef ! " FIXME ! "def Test_use_import_in_mapping() ! " var lines =<< trim END ! " vim9script ! " export def Funcx() ! " g:result = 42 ! " enddef ! " END ! " writefile(lines, 'XsomeExport.vim') ! " lines =<< trim END ! " vim9script ! " import './XsomeExport.vim' as some ! " var Funcy = some.Funcx ! " nnoremap :call Funcy() ! " END ! " writefile(lines, 'Xmapscript.vim') ! " ! " source Xmapscript.vim ! " feedkeys("\", "xt") ! " assert_equal(42, g:result) ! " ! " unlet g:result ! " delete('XsomeExport.vim') ! " delete('Xmapscript.vim') ! " nunmap ! "enddef def Test_vim9script_mix() var lines =<< trim END *************** *** 1754,1760 **** CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') CheckScriptFailure(['export var some = 123'], 'E1042:') - CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1048:') CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:') CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:') --- 1667,1672 ---- *************** *** 1802,1815 **** vim9script noclear g:loadCount += 1 var s:reloaded = 'init' ! import exported from './XExportReload' def Again(): string return 'again' enddef ! import TheFunc from './XExportReload' ! TheFunc() if exists('s:loaded') | finish | endif var s:loaded = true --- 1714,1726 ---- vim9script noclear g:loadCount += 1 var s:reloaded = 'init' ! import './XExportReload' as exp def Again(): string return 'again' enddef ! exp.TheFunc() if exists('s:loaded') | finish | endif var s:loaded = true *************** *** 1817,1823 **** var s:notReloaded = 'yes' s:reloaded = 'first' def g:Values(): list ! return [s:reloaded, s:notReloaded, Again(), Once(), exported] enddef def Once(): string --- 1728,1734 ---- var s:notReloaded = 'yes' s:reloaded = 'first' def g:Values(): list ! return [s:reloaded, s:notReloaded, Again(), Once(), exp.exported] enddef def Once(): string *************** *** 2022,2035 **** var lines =<< trim END vim9script ! import FastSort from './Xsort.vim' def Test() ! g:result = FastSort() enddef Test() # using a function imported with "as" ! import * as anAlias from './Xsort.vim' assert_equal('yes', anAlias.GetString('yes')) # using the function from a compiled function --- 1933,1946 ---- var lines =<< trim END vim9script ! import './Xsort.vim' def Test() ! g:result = Xsort.FastSort() enddef Test() # using a function imported with "as" ! import './Xsort.vim' as anAlias assert_equal('yes', anAlias.GetString('yes')) # using the function from a compiled function *************** *** 2075,2087 **** var lines =<< trim END vim9script ! import {FilterFunc, FastFilter, FastFilterDirect} from './Xfilter.vim' def Test() ! var x: list = FastFilter() enddef Test() def TestDirect() ! var x: list = FastFilterDirect() enddef TestDirect() END --- 1986,1998 ---- var lines =<< trim END vim9script ! import './Xfilter.vim' as filter def Test() ! var x: list = filter.FastFilter() enddef Test() def TestDirect() ! var x: list = filter.FastFilterDirect() enddef TestDirect() END *************** *** 2155,2165 **** def Test_import_absolute() var import_lines = [ 'vim9script', ! 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"', 'def UseExported()', ! ' g:imported_abs = exported', ! ' exported = 8888', ! ' g:imported_after = exported', 'enddef', 'UseExported()', 'g:import_disassembled = execute("disass UseExported")', --- 2066,2076 ---- def Test_import_absolute() var import_lines = [ 'vim9script', ! 'import "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim" as abs', 'def UseExported()', ! ' g:imported_abs = abs.exported', ! ' abs.exported = 8888', ! ' g:imported_after = abs.exported', 'enddef', 'UseExported()', 'g:import_disassembled = execute("disass UseExported")', *************** *** 2172,2184 **** assert_equal(9876, g:imported_abs) assert_equal(8888, g:imported_after) assert_match('\d\+_UseExported\_s*' .. ! 'g:imported_abs = exported\_s*' .. '0 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. '1 STOREG g:imported_abs\_s*' .. ! 'exported = 8888\_s*' .. '2 PUSHNR 8888\_s*' .. '3 STORESCRIPT exported-2 in .*Xexport_abs.vim\_s*' .. ! 'g:imported_after = exported\_s*' .. '4 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. '5 STOREG g:imported_after', g:import_disassembled) --- 2083,2095 ---- assert_equal(9876, g:imported_abs) assert_equal(8888, g:imported_after) assert_match('\d\+_UseExported\_s*' .. ! 'g:imported_abs = abs.exported\_s*' .. '0 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. '1 STOREG g:imported_abs\_s*' .. ! 'abs.exported = 8888\_s*' .. '2 PUSHNR 8888\_s*' .. '3 STORESCRIPT exported-2 in .*Xexport_abs.vim\_s*' .. ! 'g:imported_after = abs.exported\_s*' .. '4 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' .. '5 STOREG g:imported_after', g:import_disassembled) *************** *** 2194,2201 **** def Test_import_rtp() var import_lines = [ 'vim9script', ! 'import exported from "Xexport_rtp.vim"', ! 'g:imported_rtp = exported', ] writefile(import_lines, 'Ximport_rtp.vim') mkdir('import', 'p') --- 2105,2112 ---- def Test_import_rtp() var import_lines = [ 'vim9script', ! 'import "Xexport_rtp.vim" as rtp', ! 'g:imported_rtp = rtp.exported', ] writefile(import_lines, 'Ximport_rtp.vim') mkdir('import', 'p') *************** *** 2225,2233 **** var import_lines = [ 'vim9script', ! 'import ExpFunc from "./Xexported.vim"', 'def ImpFunc()', ! ' echo ExpFunc()', 'enddef', 'defcompile', ] --- 2136,2144 ---- var import_lines = [ 'vim9script', ! 'import "./Xexported.vim" as expo', 'def ImpFunc()', ! ' echo expo.ExpFunc()', 'enddef', 'defcompile', ] *************** *** 2279,2294 **** var lines =<< trim END vim9script ! import Func from './XexportedFunc.vim' def Func() echo 'local to function' enddef END ! CheckScriptFailure(lines, 'E1041:') lines =<< trim END vim9script ! import Func from './XexportedFunc.vim' def Outer() def Func() echo 'local to function' --- 2190,2205 ---- var lines =<< trim END vim9script ! import './XexportedFunc.vim' as Func def Func() echo 'local to function' enddef END ! CheckScriptFailure(lines, 'E1236:') lines =<< trim END vim9script ! import './XexportedFunc.vim' as Func def Outer() def Func() echo 'local to function' *************** *** 2296,2302 **** enddef defcompile END ! CheckScriptFailure(lines, 'E1073:') delete('XexportedFunc.vim') enddef --- 2207,2213 ---- enddef defcompile END ! CheckScriptFailure(lines, 'E1236:') delete('XexportedFunc.vim') enddef *************** *** 3941,3955 **** call assert_equal('global', global) call assert_equal('global', g:global) ! " imported variable becomes script-local ! import exported from './Xvim9_script.vim' ! call assert_equal('exported', s:exported) ! call assert_false(exists('exported')) ! ! " imported function becomes script-local ! import GetText from './Xvim9_script.vim' ! call assert_equal('text', s:GetText()) ! call assert_false(exists('*GetText')) END writefile(legacy_lines, 'Xlegacy_script.vim') --- 3852,3866 ---- call assert_equal('global', global) call assert_equal('global', g:global) ! "" imported variable becomes script-local ! "import exported from './Xvim9_script.vim' ! "call assert_equal('exported', s:exported) ! "call assert_false(exists('exported')) ! ! "" imported function becomes script-local ! "import GetText from './Xvim9_script.vim' ! "call assert_equal('text', s:GetText()) ! "call assert_false(exists('*GetText')) END writefile(legacy_lines, 'Xlegacy_script.vim') *************** *** 4248,4254 **** writefile(export_lines, 'rtp/syntax/Xexport.vim') var import_lines =<< trim END vim9script ! import That from './Xexport.vim' END writefile(import_lines, 'rtp/syntax/vim.vim') var save_rtp = &rtp --- 4159,4166 ---- writefile(export_lines, 'rtp/syntax/Xexport.vim') var import_lines =<< trim END vim9script ! import './Xexport.vim' as exp ! echo exp.That END writefile(import_lines, 'rtp/syntax/vim.vim') var save_rtp = &rtp *************** *** 4594,4629 **** unlet g:guard enddef ! def Test_import_gone_when_sourced_twice() ! var exportlines =<< trim END ! vim9script ! if exists('g:guard') ! finish ! endif ! g:guard = 1 ! export var name = 'someName' ! END ! writefile(exportlines, 'XexportScript.vim') ! ! var lines =<< trim END ! vim9script ! import name from './XexportScript.vim' ! def g:GetName(): string ! return name ! enddef ! END ! writefile(lines, 'XscriptImport.vim') ! so XscriptImport.vim ! assert_equal('someName', g:GetName()) ! ! so XexportScript.vim ! assert_fails('call g:GetName()', 'E1149:') ! ! delfunc g:GetName ! delete('XexportScript.vim') ! delete('XscriptImport.vim') ! unlet g:guard ! enddef def Test_unsupported_commands() var lines =<< trim END --- 4506,4541 ---- unlet g:guard enddef ! "def Test_import_gone_when_sourced_twice() ! " var exportlines =<< trim END ! " vim9script ! " if exists('g:guard') ! " finish ! " endif ! " g:guard = 1 ! " export var name = 'someName' ! " END ! " writefile(exportlines, 'XexportScript.vim') ! " ! " var lines =<< trim END ! " vim9script ! " import name from './XexportScript.vim' ! " def g:GetName(): string ! " return name ! " enddef ! " END ! " writefile(lines, 'XscriptImport.vim') ! " so XscriptImport.vim ! " assert_equal('someName', g:GetName()) ! " ! " so XexportScript.vim ! " assert_fails('call g:GetName()', 'E1149:') ! " ! " delfunc g:GetName ! " delete('XexportScript.vim') ! " delete('XscriptImport.vim') ! " unlet g:guard ! "enddef def Test_unsupported_commands() var lines =<< trim END *** ../vim-8.2.4018/src/version.c 2022-01-06 13:24:45.793265684 +0000 --- src/version.c 2022-01-06 21:08:38.709228246 +0000 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 4019, /**/ -- hundred-and-one symptoms of being an internet addict: 240. You think Webster's Dictionary is a directory of WEB sites. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///