To: vim_dev@googlegroups.com Subject: Patch 8.2.2597 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2597 Problem: Vim9: "import * as" does not work at script level. Solution: Implement using an imported namespace. Files: src/vim.h, src/eval.c, src/evalvars.c, src/proto/evalvars.pro, src/vim9execute.c, src/errors.h, src/vim9script.c, src/proto/vim9script.pro, src/testdir/test_vim9_script.vim *** ../vim-8.2.2596/src/vim.h 2021-03-10 13:39:46.318350557 +0100 --- src/vim.h 2021-03-13 19:57:01.831161138 +0100 *************** *** 2702,2705 **** --- 2702,2710 ---- #define MCH_DELAY_IGNOREINPUT 1 #define MCH_DELAY_SETTMODE 2 + // Flags for eval_variable(). + #define EVAL_VAR_VERBOSE 1 // may give error message + #define EVAL_VAR_NOAUTOLOAD 2 // do not use script autoloading + #define EVAL_VAR_IMPORT 4 // may return special variable for import + #endif // VIM__H *** ../vim-8.2.2596/src/eval.c 2021-03-06 18:18:15.370336953 +0100 --- src/eval.c 2021-03-13 20:55:08.555780587 +0100 *************** *** 1370,1376 **** // handle +=, -=, *=, /=, %= and .= di = NULL; if (eval_variable(lp->ll_name, (int)STRLEN(lp->ll_name), ! &tv, &di, TRUE, FALSE) == OK) { if ((di == NULL || (!var_check_ro(di->di_flags, lp->ll_name, FALSE) --- 1370,1376 ---- // 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) *************** *** 3500,3506 **** ret = OK; } else ! ret = eval_variable(s, len, rettv, NULL, TRUE, FALSE); } else { --- 3500,3507 ---- ret = OK; } else ! ret = eval_variable(s, len, rettv, NULL, ! EVAL_VAR_VERBOSE + EVAL_VAR_IMPORT); } else { *************** *** 5760,5765 **** --- 5761,5823 ---- check_white = FALSE; } + if (rettv->v_type == VAR_ANY) + { + char_u *exp_name; + int cc; + int idx; + ufunc_T *ufunc; + type_T *type; + + // Found script from "import * as {name}", script item name must + // follow. + if (**arg != '.') + { + if (verbose) + semsg(_(e_expected_str_but_got_str), "'.'", *arg); + ret = FAIL; + break; + } + ++*arg; + if (IS_WHITE_OR_NUL(**arg)) + { + if (verbose) + emsg(_(e_no_white_space_allowed_after_dot)); + ret = FAIL; + break; + } + + // isolate the name + exp_name = *arg; + while (eval_isnamec(**arg)) + ++*arg; + cc = **arg; + **arg = NUL; + + idx = find_exported(rettv->vval.v_number, exp_name, &ufunc, &type, + evalarg->eval_cctx, verbose); + **arg = cc; + *arg = skipwhite(*arg); + + if (idx < 0 && ufunc == NULL) + { + ret = FAIL; + break; + } + if (idx >= 0) + { + scriptitem_T *si = SCRIPT_ITEM(rettv->vval.v_number); + svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; + + copy_tv(sv->sv_tv, rettv); + } + else + { + rettv->v_type = VAR_FUNC; + rettv->vval.v_string = vim_strsave(ufunc->uf_name); + } + } + if ((**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC || rettv->v_type == VAR_PARTIAL)) && (!check_white || !VIM_ISWHITE(*(*arg - 1)))) *** ../vim-8.2.2596/src/evalvars.c 2021-03-08 20:47:09.733874887 +0100 --- src/evalvars.c 2021-03-13 20:49:53.628437349 +0100 *************** *** 1219,1225 **** arg = skipwhite(arg); if (tofree != NULL) name = tofree; ! if (eval_variable(name, len, &tv, NULL, TRUE, FALSE) == FAIL) error = TRUE; else { --- 1219,1226 ---- arg = skipwhite(arg); if (tofree != NULL) name = tofree; ! if (eval_variable(name, len, &tv, NULL, ! EVAL_VAR_VERBOSE) == FAIL) error = TRUE; else { *************** *** 2539,2544 **** --- 2540,2547 ---- /* * Get the value of internal variable "name". + * If "flags" has EVAL_VAR_IMPORT may return a VAR_ANY with v_number set to the + * imported script ID. * Return OK or FAIL. If OK is returned "rettv" must be cleared. */ int *************** *** 2547,2558 **** int len, // length of "name" typval_T *rettv, // NULL when only checking existence dictitem_T **dip, // non-NULL when typval's dict item is needed ! int verbose, // may give error message ! int no_autoload) // do not use script autoloading { int ret = OK; typval_T *tv = NULL; ! int foundFunc = FALSE; dictitem_T *v; int cc; --- 2550,2560 ---- int len, // length of "name" 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 { int ret = OK; typval_T *tv = NULL; ! int found = FALSE; dictitem_T *v; int cc; *************** *** 2561,2567 **** name[len] = NUL; // Check for user-defined variables. ! v = find_var(name, NULL, no_autoload); if (v != NULL) { tv = &v->di_tv; --- 2563,2569 ---- name[len] = NUL; // Check for user-defined variables. ! v = find_var(name, NULL, flags & EVAL_VAR_NOAUTOLOAD); if (v != NULL) { tv = &v->di_tv; *************** *** 2581,2587 **** { if (import->imp_funcname != NULL) { ! foundFunc = TRUE; if (rettv != NULL) { rettv->v_type = VAR_FUNC; --- 2583,2589 ---- { if (import->imp_funcname != NULL) { ! found = TRUE; if (rettv != NULL) { rettv->v_type = VAR_FUNC; *************** *** 2590,2597 **** } else if (import->imp_flags & IMP_FLAGS_STAR) { ! emsg("Sorry, 'import * as X' not implemented yet"); ! ret = FAIL; } else { --- 2592,2612 ---- } 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 { *************** *** 2607,2613 **** if (ufunc != NULL) { ! foundFunc = TRUE; if (rettv != NULL) { rettv->v_type = VAR_FUNC; --- 2622,2628 ---- if (ufunc != NULL) { ! found = TRUE; if (rettv != NULL) { rettv->v_type = VAR_FUNC; *************** *** 2617,2627 **** } } ! if (!foundFunc) { if (tv == NULL) { ! if (rettv != NULL && verbose) semsg(_(e_undefined_variable_str), name); ret = FAIL; } --- 2632,2642 ---- } } ! if (!found) { if (tv == NULL) { ! if (rettv != NULL && (flags & EVAL_VAR_VERBOSE)) semsg(_(e_undefined_variable_str), name); ret = FAIL; } *************** *** 3695,3701 **** { if (tofree != NULL) name = tofree; ! n = (eval_variable(name, len, &tv, NULL, FALSE, TRUE) == OK); if (n) { // handle d.key, l[idx], f(expr) --- 3710,3717 ---- { if (tofree != NULL) name = tofree; ! n = (eval_variable(name, len, &tv, NULL, ! EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT) == OK); if (n) { // handle d.key, l[idx], f(expr) *** ../vim-8.2.2596/src/proto/evalvars.pro 2021-03-03 21:22:37.178739531 +0100 --- src/proto/evalvars.pro 2021-03-13 20:12:00.957184043 +0100 *************** *** 56,62 **** 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 verbose, int no_autoload); 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); --- 56,62 ---- 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); *** ../vim-8.2.2596/src/vim9execute.c 2021-03-08 21:47:09.664648818 +0100 --- src/vim9execute.c 2021-03-13 20:05:46.021989741 +0100 *************** *** 1765,1771 **** goto failed; SOURCING_LNUM = iptr->isn_lnum; if (eval_variable(name, (int)STRLEN(name), ! STACK_TV_BOT(0), NULL, TRUE, FALSE) == FAIL) goto on_error; ++ectx.ec_stack.ga_len; } --- 1765,1771 ---- goto failed; 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; } *** ../vim-8.2.2596/src/errors.h 2021-02-28 16:55:07.513026844 +0100 --- src/errors.h 2021-03-13 20:02:53.554367234 +0100 *************** *** 373,375 **** --- 373,377 ---- INIT(= N_("E1167: Argument name shadows existing variable: %s")); EXTERN char e_argument_already_declared_in_script_str[] INIT(= N_("E1168: Argument already declared in the script: %s")); + EXTERN char e_import_as_name_not_supported_here[] + INIT(= N_("E1169: 'import * as {name}' not supported here")); *** ../vim-8.2.2596/src/vim9script.c 2021-03-10 13:39:46.322350547 +0100 --- src/vim9script.c 2021-03-13 20:54:50.315818631 +0100 *************** *** 257,263 **** char_u *name, ufunc_T **ufunc, type_T **type, ! cctx_T *cctx) { int idx = -1; svar_T *sv; --- 257,264 ---- char_u *name, ufunc_T **ufunc, type_T **type, ! cctx_T *cctx, ! int verbose) { int idx = -1; svar_T *sv; *************** *** 271,277 **** sv = ((svar_T *)script->sn_var_vals.ga_data) + idx; if (!sv->sv_export) { ! semsg(_(e_item_not_exported_in_script_str), name); return -1; } *type = sv->sv_type; --- 272,279 ---- sv = ((svar_T *)script->sn_var_vals.ga_data) + idx; if (!sv->sv_export) { ! if (verbose) ! semsg(_(e_item_not_exported_in_script_str), name); return -1; } *type = sv->sv_type; *************** *** 301,307 **** if (*ufunc == NULL) { ! semsg(_(e_item_not_found_in_script_str), name); return -1; } } --- 303,310 ---- if (*ufunc == NULL) { ! if (verbose) ! semsg(_(e_item_not_found_in_script_str), name); return -1; } } *************** *** 532,538 **** ufunc_T *ufunc = NULL; type_T *type; ! idx = find_exported(sid, name, &ufunc, &type, cctx); if (idx < 0 && ufunc == NULL) goto erret; --- 535,541 ---- ufunc_T *ufunc = NULL; type_T *type; ! idx = find_exported(sid, name, &ufunc, &type, cctx, TRUE); if (idx < 0 && ufunc == NULL) goto erret; *** ../vim-8.2.2596/src/proto/vim9script.pro 2021-02-11 21:19:30.522147936 +0100 --- src/proto/vim9script.pro 2021-03-13 20:54:02.211918980 +0100 *************** *** 7,13 **** void free_imports_and_script_vars(int sid); void mark_imports_for_reload(int sid); void ex_import(exarg_T *eap); ! int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx); char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid, evalarg_T *evalarg, void *cctx); 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); --- 7,13 ---- void free_imports_and_script_vars(int sid); void mark_imports_for_reload(int sid); void ex_import(exarg_T *eap); ! int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx, int verbose); char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid, evalarg_T *evalarg, void *cctx); 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); *** ../vim-8.2.2596/src/testdir/test_vim9_script.vim 2021-03-10 14:00:15.571489906 +0100 --- src/testdir/test_vim9_script.vim 2021-03-13 20:51:35.688224516 +0100 *************** *** 1031,1043 **** vim9script import * as Export from './Xexport.vim' def UseExport() ! g:imported = Export.exported enddef UseExport() END writefile(import_star_as_lines, 'Ximport.vim') source Ximport.vim ! assert_equal(9883, g:imported) var import_star_as_lines_no_dot =<< trim END vim9script --- 1031,1047 ---- vim9script import * as Export from './Xexport.vim' def UseExport() ! g:imported_def = Export.exported enddef + g:imported_script = Export.exported + assert_equal(1, exists('Export.exported')) + assert_equal(0, exists('Export.notexported')) UseExport() END writefile(import_star_as_lines, 'Ximport.vim') source Ximport.vim ! assert_equal(9883, g:imported_def) ! assert_equal(9883, g:imported_script) var import_star_as_lines_no_dot =<< trim END vim9script *************** *** 1072,1077 **** --- 1076,1097 ---- writefile(import_star_as_duplicated, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1073:', '', 4, 'Ximport.vim') + 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') + assert_fails('source Ximport.vim', 'E1029:') + + 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') + assert_fails('source Ximport.vim', 'E1074:') + var import_star_as_lines_missing_name =<< trim END vim9script import * as Export from './Xexport.vim' *** ../vim-8.2.2596/src/version.c 2021-03-13 15:47:51.577753545 +0100 --- src/version.c 2021-03-13 19:39:18.049496738 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2597, /**/ -- BEDEVERE: Wait. Wait ... tell me, what also floats on water? ALL: Bread? No, no, no. Apples .... gravy ... very small rocks ... ARTHUR: A duck. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///