summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-01-06 21:10:28 +0000
committerBram Moolenaar <Bram@vim.org>2022-01-06 21:10:28 +0000
commitd5f400c607182db6d4fbe2964471d796277f67e8 (patch)
tree285e08dceecf77069c17d1c513e3c918140b18dc
parent18f4740f043b353abe47b7a00131317052457686 (diff)
patch 8.2.4019: Vim9: import mechanism is too complicatedv8.2.4019
Problem: Vim9: import mechanism is too complicated. Solution: Do not use the Javascript mechanism but a much simpler one.
-rw-r--r--runtime/doc/vim9.txt38
-rw-r--r--src/errors.h16
-rw-r--r--src/eval.c75
-rw-r--r--src/evalvars.c105
-rw-r--r--src/proto/eval.pro3
-rw-r--r--src/proto/evalvars.pro4
-rw-r--r--src/proto/vim9script.pro2
-rw-r--r--src/structs.h15
-rw-r--r--src/testdir/test_vim9_assign.vim6
-rw-r--r--src/testdir/test_vim9_script.vim416
-rw-r--r--src/userfunc.c72
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c32
-rw-r--r--src/vim9execute.c4
-rw-r--r--src/vim9expr.c89
-rw-r--r--src/vim9script.c260
16 files changed, 472 insertions, 667 deletions
diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt
index e79e06e5bb..5d3e5b1bb0 100644
--- a/runtime/doc/vim9.txt
+++ b/runtime/doc/vim9.txt
@@ -1432,24 +1432,27 @@ be exported. {not implemented yet: class, interface}
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"
+The exported items can be imported in another Vim9 script: >
+ import "myscript.vim"
-To import multiple items at the same time: >
- import {someValue, MyClass} from "thatscript.vim"
+This makes each item available as "myscript.item".
-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'
+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", 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.
+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,6 +1473,9 @@ The script name after `import` can be:
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,9 +1497,9 @@ actually needed. A recommended mechanism:
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"
+ import "../import/someother.vim" as other
def searchfor#Stuff(arg: string)
- var filtered = FilterFunc(arg)
+ 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
diff --git a/src/errors.h b/src/errors.h
index 2d164cd9f0..5aaaeacd8d 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -2500,8 +2500,8 @@ EXTERN char e_white_space_required_after_str_str[]
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_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,8 +2839,8 @@ EXTERN char e_legacy_must_be_followed_by_command[]
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_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,3 +2881,11 @@ EXTERN char e_cmd_mapping_must_end_with_cr[]
INIT(= N_("E1255: <Cmd> mapping must end with <CR>"));
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"));
diff --git a/src/eval.c b/src/eval.c
index 2e370c1b2f..fe4dbd10bb 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -56,7 +56,6 @@ static int eval7_leader(typval_T *rettv, int numeric_only, char_u *start_leader,
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.
@@ -922,9 +921,37 @@ get_lval(
}
}
}
+ 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 != '.') || lp->ll_name == NULL)
+ if ((*p != '[' && *p != '.'))
return p;
if (in_vim9script() && lval_root != NULL)
@@ -997,7 +1024,7 @@ get_lval(
&& lp->ll_tv == &v->di_tv
&& ht != NULL && ht == get_script_local_ht())
{
- svar_T *sv = find_typval_in_script(lp->ll_tv);
+ svar_T *sv = find_typval_in_script(lp->ll_tv, 0);
// Vim9 script local variable: get the type
if (sv != NULL)
@@ -1359,13 +1386,13 @@ set_var_lval(
// handle +=, -=, *=, /=, %= and .=
di = NULL;
if (eval_variable(lp->ll_name, (int)STRLEN(lp->ll_name),
- &tv, &di, EVAL_VAR_VERBOSE) == OK)
+ 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, NULL, &tv, FALSE,
+ set_var_const(lp->ll_name, lp->ll_sid, NULL, &tv, FALSE,
ASSIGN_NO_DECL, 0);
clear_tv(&tv);
}
@@ -1375,7 +1402,7 @@ set_var_lval(
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,
+ set_var_const(lp->ll_name, lp->ll_sid, lp->ll_type, rettv, copy,
flags, var_idx);
}
*endp = cc;
@@ -1389,7 +1416,7 @@ set_var_lval(
if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
&& (flags & ASSIGN_FOR_LOOP) == 0)
{
- emsg(_("E996: Cannot lock a range"));
+ emsg(_(e_cannot_lock_range));
return;
}
@@ -1404,7 +1431,7 @@ set_var_lval(
if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
&& (flags & ASSIGN_FOR_LOOP) == 0)
{
- emsg(_("E996: Cannot lock a list or dict"));
+ emsg(_(e_cannot_lock_list_or_dict));
return;
}
@@ -2089,7 +2116,7 @@ getline_peek_skip_comments(evalarg_T *evalarg)
* FALSE.
* "arg" must point somewhere inside a line, not at the start.
*/
- static char_u *
+ char_u *
eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
{
char_u *p = skipwhite(arg);
@@ -2120,7 +2147,7 @@ eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
* To be called after eval_next_non_blank() sets "getnext" to TRUE.
* Only called for Vim9 script.
*/
- static char_u *
+ char_u *
eval_next_line(evalarg_T *evalarg)
{
garray_T *gap = &evalarg->eval_ga;
@@ -2236,13 +2263,28 @@ eval0(
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 = TRUE;
+ int check_for_end = retarg == NULL;
int end_error = FALSE;
p = skipwhite(arg);
@@ -2253,7 +2295,7 @@ eval0(
// 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)
+ if (in_vim9script() && p > expr_end && retarg == NULL)
while (*p == '#')
{
char_u *nl = vim_strchr(p, NL);
@@ -2298,7 +2340,9 @@ eval0(
return FAIL;
}
- if (check_for_end && eap != NULL)
+ if (retarg != NULL)
+ *retarg = p;
+ else if (check_for_end && eap != NULL)
set_nextcmd(eap, p);
return ret;
@@ -3669,7 +3713,7 @@ eval7(
ret = OK;
}
else
- ret = eval_variable(s, len, rettv, NULL,
+ ret = eval_variable(s, len, 0, rettv, NULL,
EVAL_VAR_VERBOSE + EVAL_VAR_IMPORT);
}
else
@@ -5887,7 +5931,7 @@ handle_subscript(
ufunc_T *ufunc;
type_T *type;
- // Found script from "import * as {name}", script item name must
+ // Found script from "import {name} as name", script item name must
// follow.
if (**arg != '.')
{
@@ -5934,6 +5978,7 @@ handle_subscript(
rettv->v_type = VAR_FUNC;
rettv->vval.v_string = vim_strsave(ufunc->uf_name);
}
+ continue;
}
if ((**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
diff --git a/src/evalvars.c b/src/evalvars.c
index 055d49f5ef..2de6f224b7 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -1232,7 +1232,7 @@ list_arg_vars(exarg_T *eap, char_u *arg, int *first)
arg = skipwhite(arg);
if (tofree != NULL)
name = tofree;
- if (eval_variable(name, len, &tv, NULL,
+ if (eval_variable(name, len, 0, &tv, NULL,
EVAL_VAR_VERBOSE) == FAIL)
error = TRUE;
else
@@ -2645,6 +2645,7 @@ set_cmdarg(exarg_T *eap, char_u *oldarg)
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,48 +2679,50 @@ eval_variable(
if (tv == NULL && (in_vim9script() || STRNCMP(name, "s:", 2) == 0))
{
- imported_T *import;
+ imported_T *import = NULL;
char_u *p = STRNCMP(name, "s:", 2) == 0 ? name + 2 : name;
- import = find_imported(p, 0, NULL);
+ if (sid == 0)
+ import = find_imported(p, 0, NULL);
// imported variable from another script
- if (import != NULL)
+ if (import != NULL || sid != 0)
{
- if (import->imp_funcname != NULL)
+ if ((flags & EVAL_VAR_IMPORT) == 0)
{
- found = TRUE;
- if (rettv != NULL)
+ if (sid != 0 && SCRIPT_ID_VALID(sid))
{
- rettv->v_type = VAR_FUNC;
- rettv->vval.v_string = vim_strsave(import->imp_funcname);
+ 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 (import->imp_flags & IMP_FLAGS_STAR)
- {
- if ((flags & EVAL_VAR_IMPORT) == 0)
+ 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 = 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;
+ 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,7 +2763,7 @@ eval_variable(
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);
+ svar_T *sv = find_typval_in_script(tv, 0);
if (sv != NULL)
type = sv->sv_type;
@@ -3278,17 +3281,19 @@ set_var(
typval_T *tv,
int copy) // make copy of value in "tv"
{
- set_var_const(name, NULL, tv, copy, ASSIGN_DECL, 0);
+ 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,20 +3306,27 @@ set_var_const(
dictitem_T *di;
typval_T *dest_tv = NULL;
char_u *varname;
- hashtab_T *ht;
+ 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
- ht = find_var_ht(name, &varname);
+ 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();
+ is_script_local = ht == get_script_local_ht() || sid != 0;
if (vim9script
&& !is_script_local
@@ -3347,33 +3359,14 @@ set_var_const(
if (import != NULL)
{
- scriptitem_T *si = SCRIPT_ITEM(import->imp_sid);
- svar_T *sv;
- where_T where = WHERE_INIT;
-
- // imported variable from another script
+ // imported name space cannot be used
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);
+ semsg(_(e_cannot_use_str_itself_it_is_imported), name);
+ goto failed;
}
}
@@ -3419,7 +3412,7 @@ set_var_const(
if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0)
{
where_T where = WHERE_INIT;
- svar_T *sv = find_typval_in_script(&di->di_tv);
+ svar_T *sv = find_typval_in_script(&di->di_tv, sid);
if (sv != NULL)
{
@@ -3956,7 +3949,7 @@ var_exists(char_u *var)
{
if (tofree != NULL)
name = tofree;
- n = (eval_variable(name, len, &tv, NULL,
+ n = (eval_variable(name, len, 0, &tv, NULL,
EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT) == OK);
if (n)
{
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
index dc9c53b516..f7fa647375 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -33,10 +33,13 @@ int next_for_item(void *fi_void, char_u *arg);
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);
diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro
index 9fb2c77b52..de1f7a1f3d 100644
--- a/src/proto/evalvars.pro
+++ b/src/proto/evalvars.pro
@@ -57,7 +57,7 @@ void set_reg_var(int c);
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);
+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,7 +72,7 @@ void vars_clear(hashtab_T *ht);
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);
+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);
diff --git a/src/proto/vim9script.pro b/src/proto/vim9script.pro
index 1b21819235..264482493e 100644
--- a/src/proto/vim9script.pro
+++ b/src/proto/vim9script.pro
@@ -15,7 +15,7 @@ int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T
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);
+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 : */
diff --git a/src/structs.h b/src/structs.h
index 1a764e170c..197df720c5 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1822,19 +1822,10 @@ struct svar_S {
typedef struct {
char_u *imp_name; // name imported as (allocated)
- int imp_sid; // script ID of "from"
-
+ scid_T 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
/*
@@ -4264,6 +4255,10 @@ typedef struct lval_S
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.
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index 209ac95f84..80ee6b71f6 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -2109,13 +2109,13 @@ def Test_unlet()
writefile(['vim9script', 'export var svar = 1234'], 'XunletExport.vim')
var lines =<< trim END
vim9script
- import svar from './XunletExport.vim'
+ import './XunletExport.vim' as exp
def UnletSvar()
- unlet svar
+ unlet exp.svar
enddef
defcompile
END
- CheckScriptFailure(lines, 'E1081:', 1)
+ CheckScriptFailure(lines, 'E1260:', 1)
delete('XunletExport.vim')
$ENVVAR = 'foobar'
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 8aea267591..4c5d9e9a0d 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -1172,47 +1172,43 @@ def Undo_export_script_lines()
enddef
def Test_vim9_import_export()
+ writefile(s:export_script_lines, 'Xexport.vim')
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()
+ var dir = './'
+ var ext = ".vim"
+ import dir .. 'Xexport' .. ext as expo
- import ExportedInc from './Xexport.vim'
- ExportedInc()
- g:exported_i1 = exported
- g:exported_i2 = ExportedValue()
+ 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()
- exported = 11
- g:exported_s1 = exported
- g:exported_s2 = ExportedValue()
+ expo.exported = 11
+ g:exported_s1 = expo.exported
+ g:exported_s2 = expo.ExportedValue()
- g:imported_func = Exported()
+ g:imported_func = expo.Exported()
def GetExported(): string
- var local_dict = {ref: Exported}
+ var local_dict = {ref: expo.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
+ g:imported_name = expo.exp_name
+ expo.exp_name ..= ' Doe'
+ g:imported_name_appended = expo.exp_name
+ g:exported_later = expo.exported
- import theList from './Xexport.vim'
- theList->add(2)
- assert_equal([1, 2], theList)
+ expo.theList->add(2)
+ assert_equal([1, 2], expo.theList)
END
-
writefile(import_script_lines, 'Ximport.vim')
- writefile(s:export_script_lines, 'Xexport.vim')
-
source Ximport.vim
assert_equal('bobbie', g:result)
@@ -1248,16 +1244,12 @@ def Test_vim9_import_export()
# 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()
+ 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,7 +1267,7 @@ def Test_vim9_import_export()
var import_star_as_lines =<< trim END
vim9script
- import * as Export from './Xexport.vim'
+ import './Xexport.vim' as Export
def UseExport()
g:exported_def = Export.exported
enddef
@@ -1294,7 +1286,7 @@ def Test_vim9_import_export()
var import_star_as_lines_no_dot =<< trim END
vim9script
- import * as Export from './Xexport.vim'
+ import './Xexport.vim' as Export
def Func()
var dummy = 1
var imported = Export + dummy
@@ -1306,7 +1298,7 @@ def Test_vim9_import_export()
var import_star_as_lines_dot_space =<< trim END
vim9script
- import * as Export from './Xexport.vim'
+ import './Xexport.vim' as Export
def Func()
var imported = Export . exported
enddef
@@ -1317,8 +1309,8 @@ def Test_vim9_import_export()
var import_func_duplicated =<< trim END
vim9script
- import ExportedInc from './Xexport.vim'
- import ExportedInc from './Xexport.vim'
+ import './Xexport.vim' as expo
+ import './Xexport.vim' as expo
ExportedInc()
END
@@ -1327,9 +1319,9 @@ def Test_vim9_import_export()
var import_star_as_duplicated =<< trim END
vim9script
- import * as Export from './Xexport.vim'
+ import './Xexport.vim' as Export
var some = 'other'
- import * as Export from './Xexport.vim'
+ import './Xexport.vim' as Export
defcompile
END
writefile(import_star_as_duplicated, 'Ximport.vim')
@@ -1337,7 +1329,7 @@ def Test_vim9_import_export()
var import_star_as_lines_script_no_dot =<< trim END
vim9script
- import * as Export from './Xexport.vim'
+ import './Xexport.vim' as Export
g:imported_script = Export exported
END
writefile(import_star_as_lines_script_no_dot, 'Ximport.vim')
@@ -1345,7 +1337,7 @@ def Test_vim9_import_export()
var import_star_as_lines_script_space_after_dot =<< trim END
vim9script
- import * as Export from './Xexport.vim'
+ import './Xexport.vim' as Export
g:imported_script = Export. exported
END
writefile(import_star_as_lines_script_space_after_dot, 'Ximport.vim')
@@ -1353,7 +1345,7 @@ def Test_vim9_import_export()
var import_star_as_lines_missing_name =<< trim END
vim9script
- import * as Export from './Xexport.vim'
+ import './Xexport.vim' as Export
def Func()
var imported = Export.
enddef
@@ -1364,10 +1356,8 @@ def Test_vim9_import_export()
var import_star_as_lbr_lines =<< trim END
vim9script
- import *
+ import './Xexport.vim'
as Export
- from
- './Xexport.vim'
def UseExport()
g:exported = Export.exported
enddef
@@ -1378,44 +1368,20 @@ def Test_vim9_import_export()
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
+ # try to use something that exists but is not exported
var import_not_exported_lines =<< trim END
vim9script
- import name from './Xexport.vim'
+ import './Xexport.vim' as expo
+ echo expo.name
END
writefile(import_not_exported_lines, 'Ximport.vim')
- assert_fails('source Ximport.vim', 'E1049:', '', 2, '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 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'
+ import './Xexport.vim' as exported
END
writefile(import_already_defined, 'Ximport.vim')
assert_fails('source Ximport.vim', 'E1054:', '', 3, 'Ximport.vim')
@@ -1423,9 +1389,9 @@ def Test_vim9_import_export()
# try changing an imported const
var import_assign_to_const =<< trim END
vim9script
- import CONST from './Xexport.vim'
+ import './Xexport.vim' as expo
def Assign()
- CONST = 987
+ expo.CONST = 987
enddef
defcompile
END
@@ -1435,54 +1401,39 @@ def Test_vim9_import_export()
# try changing an imported final
var import_assign_to_final =<< trim END
vim9script
- import theList from './Xexport.vim'
+ import './Xexport.vim' as expo
def Assign()
- theList = [2]
+ expo.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
+ var import_no_as_lines =<< trim END
vim9script
- import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim'
+ import './Xexport.vim' name
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')
+ 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 name from Xexport.vim
+ 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 name from './XnoExport.vim'
+ import './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