18a7d6542SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet: 28a7d6542SBram Moolenaar * 38a7d6542SBram Moolenaar * VIM - Vi IMproved by Bram Moolenaar 48a7d6542SBram Moolenaar * 58a7d6542SBram Moolenaar * Do ":help uganda" in Vim to read copying and usage conditions. 68a7d6542SBram Moolenaar * Do ":help credits" in Vim to see a list of people who contributed. 78a7d6542SBram Moolenaar * See README.txt for an overview of the Vim source code. 88a7d6542SBram Moolenaar */ 98a7d6542SBram Moolenaar 108a7d6542SBram Moolenaar /* 118a7d6542SBram Moolenaar * vim9script.c: :vim9script, :import, :export and friends 128a7d6542SBram Moolenaar */ 138a7d6542SBram Moolenaar 148a7d6542SBram Moolenaar #include "vim.h" 158a7d6542SBram Moolenaar 168a7d6542SBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO) 178a7d6542SBram Moolenaar 188a7d6542SBram Moolenaar #include "vim9.h" 198a7d6542SBram Moolenaar 209721fb4eSBram Moolenaar static char e_needs_vim9[] = N_("E1042: export can only be used in vim9script"); 218a7d6542SBram Moolenaar 228a7d6542SBram Moolenaar int 238a7d6542SBram Moolenaar in_vim9script(void) 248a7d6542SBram Moolenaar { 258a7d6542SBram Moolenaar // TODO: go up the stack? 268a7d6542SBram Moolenaar return current_sctx.sc_version == SCRIPT_VERSION_VIM9; 278a7d6542SBram Moolenaar } 288a7d6542SBram Moolenaar 298a7d6542SBram Moolenaar /* 308a7d6542SBram Moolenaar * ":vim9script". 318a7d6542SBram Moolenaar */ 328a7d6542SBram Moolenaar void 338a7d6542SBram Moolenaar ex_vim9script(exarg_T *eap) 348a7d6542SBram Moolenaar { 35101f4810SBram Moolenaar scriptitem_T *si; 368a7d6542SBram Moolenaar 378a7d6542SBram Moolenaar if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 388a7d6542SBram Moolenaar { 398a7d6542SBram Moolenaar emsg(_("E1038: vim9script can only be used in a script")); 408a7d6542SBram Moolenaar return; 418a7d6542SBram Moolenaar } 42101f4810SBram Moolenaar si = SCRIPT_ITEM(current_sctx.sc_sid); 438a7d6542SBram Moolenaar if (si->sn_had_command) 448a7d6542SBram Moolenaar { 458a7d6542SBram Moolenaar emsg(_("E1039: vim9script must be the first command in a script")); 468a7d6542SBram Moolenaar return; 478a7d6542SBram Moolenaar } 488a7d6542SBram Moolenaar current_sctx.sc_version = SCRIPT_VERSION_VIM9; 498a7d6542SBram Moolenaar si->sn_version = SCRIPT_VERSION_VIM9; 508a7d6542SBram Moolenaar si->sn_had_command = TRUE; 518a7d6542SBram Moolenaar 528a7d6542SBram Moolenaar if (STRCMP(p_cpo, CPO_VIM) != 0) 538a7d6542SBram Moolenaar { 548a7d6542SBram Moolenaar si->sn_save_cpo = p_cpo; 558a7d6542SBram Moolenaar p_cpo = vim_strsave((char_u *)CPO_VIM); 568a7d6542SBram Moolenaar } 57227a69deSBram Moolenaar } 588a7d6542SBram Moolenaar 598a7d6542SBram Moolenaar /* 608a7d6542SBram Moolenaar * ":export let Name: type" 618a7d6542SBram Moolenaar * ":export const Name: type" 628a7d6542SBram Moolenaar * ":export def Name(..." 638a7d6542SBram Moolenaar * ":export class Name ..." 648a7d6542SBram Moolenaar * 658a7d6542SBram Moolenaar * ":export {Name, ...}" 668a7d6542SBram Moolenaar */ 678a7d6542SBram Moolenaar void 6809689a02SBram Moolenaar ex_export(exarg_T *eap) 698a7d6542SBram Moolenaar { 708a7d6542SBram Moolenaar if (current_sctx.sc_version != SCRIPT_VERSION_VIM9) 718a7d6542SBram Moolenaar { 728a7d6542SBram Moolenaar emsg(_(e_needs_vim9)); 738a7d6542SBram Moolenaar return; 748a7d6542SBram Moolenaar } 758a7d6542SBram Moolenaar 768a7d6542SBram Moolenaar eap->cmd = eap->arg; 778a7d6542SBram Moolenaar (void)find_ex_command(eap, NULL, lookup_scriptvar, NULL); 788a7d6542SBram Moolenaar switch (eap->cmdidx) 798a7d6542SBram Moolenaar { 808a7d6542SBram Moolenaar case CMD_let: 818a7d6542SBram Moolenaar case CMD_const: 828a7d6542SBram Moolenaar case CMD_def: 838a7d6542SBram Moolenaar // case CMD_class: 848a7d6542SBram Moolenaar is_export = TRUE; 858a7d6542SBram Moolenaar do_cmdline(eap->cmd, eap->getline, eap->cookie, 868a7d6542SBram Moolenaar DOCMD_VERBOSE + DOCMD_NOWAIT); 878a7d6542SBram Moolenaar 888a7d6542SBram Moolenaar // The command will reset "is_export" when exporting an item. 898a7d6542SBram Moolenaar if (is_export) 908a7d6542SBram Moolenaar { 918a7d6542SBram Moolenaar emsg(_("E1044: export with invalid argument")); 928a7d6542SBram Moolenaar is_export = FALSE; 938a7d6542SBram Moolenaar } 948a7d6542SBram Moolenaar break; 958a7d6542SBram Moolenaar default: 968a7d6542SBram Moolenaar emsg(_("E1043: Invalid command after :export")); 978a7d6542SBram Moolenaar break; 988a7d6542SBram Moolenaar } 998a7d6542SBram Moolenaar } 1008a7d6542SBram Moolenaar 1018a7d6542SBram Moolenaar /* 1028a7d6542SBram Moolenaar * Add a new imported item entry to the current script. 1038a7d6542SBram Moolenaar */ 1048a7d6542SBram Moolenaar static imported_T * 1058a7d6542SBram Moolenaar new_imported(garray_T *gap) 1068a7d6542SBram Moolenaar { 1078a7d6542SBram Moolenaar if (ga_grow(gap, 1) == OK) 1088a7d6542SBram Moolenaar return ((imported_T *)gap->ga_data + gap->ga_len++); 1098a7d6542SBram Moolenaar return NULL; 1108a7d6542SBram Moolenaar } 1118a7d6542SBram Moolenaar 1128a7d6542SBram Moolenaar /* 1138a7d6542SBram Moolenaar * Free all imported items in script "sid". 1148a7d6542SBram Moolenaar */ 1158a7d6542SBram Moolenaar void 1168a7d6542SBram Moolenaar free_imports(int sid) 1178a7d6542SBram Moolenaar { 11821b9e977SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(sid); 1198a7d6542SBram Moolenaar int idx; 1208a7d6542SBram Moolenaar 1218a7d6542SBram Moolenaar for (idx = 0; idx < si->sn_imports.ga_len; ++idx) 1228a7d6542SBram Moolenaar { 12320431c9dSBram Moolenaar imported_T *imp = ((imported_T *)si->sn_imports.ga_data) + idx; 1248a7d6542SBram Moolenaar 1258a7d6542SBram Moolenaar vim_free(imp->imp_name); 1268a7d6542SBram Moolenaar } 1278a7d6542SBram Moolenaar ga_clear(&si->sn_imports); 12820431c9dSBram Moolenaar ga_clear(&si->sn_var_vals); 12920431c9dSBram Moolenaar ga_clear(&si->sn_type_list); 1308a7d6542SBram Moolenaar } 1318a7d6542SBram Moolenaar 1328a7d6542SBram Moolenaar /* 1338a7d6542SBram Moolenaar * ":import Item from 'filename'" 1348a7d6542SBram Moolenaar * ":import Item as Alias from 'filename'" 1358a7d6542SBram Moolenaar * ":import {Item} from 'filename'". 1368a7d6542SBram Moolenaar * ":import {Item as Alias} from 'filename'" 1378a7d6542SBram Moolenaar * ":import {Item, Item} from 'filename'" 1388a7d6542SBram Moolenaar * ":import {Item, Item as Alias} from 'filename'" 1398a7d6542SBram Moolenaar * 1408a7d6542SBram Moolenaar * ":import * as Name from 'filename'" 1418a7d6542SBram Moolenaar */ 1428a7d6542SBram Moolenaar void 1438a7d6542SBram Moolenaar ex_import(exarg_T *eap) 1448a7d6542SBram Moolenaar { 145101f4810SBram Moolenaar char_u *cmd_end; 1461c991144SBram Moolenaar evalarg_T evalarg; 1478a7d6542SBram Moolenaar 148101f4810SBram Moolenaar if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 149101f4810SBram Moolenaar { 150101f4810SBram Moolenaar emsg(_("E1094: import can only be used in a script")); 151101f4810SBram Moolenaar return; 152101f4810SBram Moolenaar } 1531c991144SBram Moolenaar fill_evalarg_from_eap(&evalarg, eap, eap->skip); 154101f4810SBram Moolenaar 1551c991144SBram Moolenaar cmd_end = handle_import(eap->arg, NULL, current_sctx.sc_sid, 1561c991144SBram Moolenaar &evalarg, NULL); 1578a7d6542SBram Moolenaar if (cmd_end != NULL) 1588a7d6542SBram Moolenaar eap->nextcmd = check_nextcmd(cmd_end); 1591c991144SBram Moolenaar clear_evalarg(&evalarg, eap); 1608a7d6542SBram Moolenaar } 1618a7d6542SBram Moolenaar 1628a7d6542SBram Moolenaar /* 163f2d5c240SBram Moolenaar * Find an exported item in "sid" matching the name at "*argp". 164f2d5c240SBram Moolenaar * When it is a variable return the index. 165f2d5c240SBram Moolenaar * When it is a user function return "*ufunc". 166f2d5c240SBram Moolenaar * When not found returns -1 and "*ufunc" is NULL. 167f2d5c240SBram Moolenaar */ 168f2d5c240SBram Moolenaar int 169f2d5c240SBram Moolenaar find_exported( 170f2d5c240SBram Moolenaar int sid, 1711c991144SBram Moolenaar char_u *name, 172f2d5c240SBram Moolenaar ufunc_T **ufunc, 173f2d5c240SBram Moolenaar type_T **type) 174f2d5c240SBram Moolenaar { 175f2d5c240SBram Moolenaar int idx = -1; 176f2d5c240SBram Moolenaar svar_T *sv; 177f2d5c240SBram Moolenaar scriptitem_T *script = SCRIPT_ITEM(sid); 178f2d5c240SBram Moolenaar 179f2d5c240SBram Moolenaar // find name in "script" 180f2d5c240SBram Moolenaar // TODO: also find script-local user function 181f2d5c240SBram Moolenaar idx = get_script_item_idx(sid, name, FALSE); 182f2d5c240SBram Moolenaar if (idx >= 0) 183f2d5c240SBram Moolenaar { 184f2d5c240SBram Moolenaar sv = ((svar_T *)script->sn_var_vals.ga_data) + idx; 185f2d5c240SBram Moolenaar if (!sv->sv_export) 186f2d5c240SBram Moolenaar { 187f2d5c240SBram Moolenaar semsg(_("E1049: Item not exported in script: %s"), name); 188f2d5c240SBram Moolenaar return -1; 189f2d5c240SBram Moolenaar } 190f2d5c240SBram Moolenaar *type = sv->sv_type; 191f2d5c240SBram Moolenaar *ufunc = NULL; 192f2d5c240SBram Moolenaar } 193f2d5c240SBram Moolenaar else 194f2d5c240SBram Moolenaar { 195f2d5c240SBram Moolenaar char_u buffer[200]; 196f2d5c240SBram Moolenaar char_u *funcname; 197f2d5c240SBram Moolenaar 198f2d5c240SBram Moolenaar // it could be a user function. 199f2d5c240SBram Moolenaar if (STRLEN(name) < sizeof(buffer) - 10) 200f2d5c240SBram Moolenaar funcname = buffer; 201f2d5c240SBram Moolenaar else 202f2d5c240SBram Moolenaar { 203f2d5c240SBram Moolenaar funcname = alloc(STRLEN(name) + 10); 204f2d5c240SBram Moolenaar if (funcname == NULL) 205f2d5c240SBram Moolenaar return -1; 206f2d5c240SBram Moolenaar } 207f2d5c240SBram Moolenaar funcname[0] = K_SPECIAL; 208f2d5c240SBram Moolenaar funcname[1] = KS_EXTRA; 209f2d5c240SBram Moolenaar funcname[2] = (int)KE_SNR; 210f2d5c240SBram Moolenaar sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name); 2114c17ad94SBram Moolenaar *ufunc = find_func(funcname, FALSE, NULL); 212f2d5c240SBram Moolenaar if (funcname != buffer) 213f2d5c240SBram Moolenaar vim_free(funcname); 214f2d5c240SBram Moolenaar 215f2d5c240SBram Moolenaar if (*ufunc == NULL) 216f2d5c240SBram Moolenaar { 217f2d5c240SBram Moolenaar semsg(_("E1048: Item not found in script: %s"), name); 218f2d5c240SBram Moolenaar return -1; 219f2d5c240SBram Moolenaar } 220f2d5c240SBram Moolenaar } 221f2d5c240SBram Moolenaar 222f2d5c240SBram Moolenaar return idx; 223f2d5c240SBram Moolenaar } 224f2d5c240SBram Moolenaar 225f2d5c240SBram Moolenaar /* 2268a7d6542SBram Moolenaar * Handle an ":import" command and add the resulting imported_T to "gap", when 2278a7d6542SBram Moolenaar * not NULL, or script "import_sid" sn_imports. 2288a7d6542SBram Moolenaar * Returns a pointer to after the command or NULL in case of failure 2298a7d6542SBram Moolenaar */ 2308a7d6542SBram Moolenaar char_u * 2311c991144SBram Moolenaar handle_import( 2321c991144SBram Moolenaar char_u *arg_start, 2331c991144SBram Moolenaar garray_T *gap, 2341c991144SBram Moolenaar int import_sid, 2351c991144SBram Moolenaar evalarg_T *evalarg, 2361c991144SBram Moolenaar void *cctx) 2378a7d6542SBram Moolenaar { 2388a7d6542SBram Moolenaar char_u *arg = arg_start; 2391c991144SBram Moolenaar char_u *cmd_end = NULL; 2401c991144SBram Moolenaar char_u *as_name = NULL; 2418a7d6542SBram Moolenaar int ret = FAIL; 2428a7d6542SBram Moolenaar typval_T tv; 2438a7d6542SBram Moolenaar int sid = -1; 2448a7d6542SBram Moolenaar int res; 2451c991144SBram Moolenaar garray_T names; 2461c991144SBram Moolenaar static char e_import_syntax[] = N_("E1047: syntax error in import"); 2478a7d6542SBram Moolenaar 2481c991144SBram Moolenaar ga_init2(&names, sizeof(char_u *), 10); 2498a7d6542SBram Moolenaar if (*arg == '{') 2508a7d6542SBram Moolenaar { 2511c991144SBram Moolenaar // "import {item, item} from ..." 2521c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg + 1, evalarg); 2531c991144SBram Moolenaar for (;;) 2541c991144SBram Moolenaar { 2551c991144SBram Moolenaar char_u *p = arg; 2561c991144SBram Moolenaar int had_comma = FALSE; 2571c991144SBram Moolenaar 2581c991144SBram Moolenaar while (eval_isnamec(*arg)) 2598a7d6542SBram Moolenaar ++arg; 2601c991144SBram Moolenaar if (p == arg) 2611c991144SBram Moolenaar break; 2621c991144SBram Moolenaar if (ga_grow(&names, 1) == FAIL) 2631c991144SBram Moolenaar goto erret; 2641c991144SBram Moolenaar ((char_u **)names.ga_data)[names.ga_len] = 2651c991144SBram Moolenaar vim_strnsave(p, arg - p); 2661c991144SBram Moolenaar ++names.ga_len; 2671c991144SBram Moolenaar if (*arg == ',') 2681c991144SBram Moolenaar { 2691c991144SBram Moolenaar had_comma = TRUE; 2701c991144SBram Moolenaar ++arg; 2711c991144SBram Moolenaar } 2721c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg, evalarg); 2738a7d6542SBram Moolenaar if (*arg == '}') 2741c991144SBram Moolenaar { 2751c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg + 1, evalarg); 2761c991144SBram Moolenaar break; 2771c991144SBram Moolenaar } 2781c991144SBram Moolenaar if (!had_comma) 2791c991144SBram Moolenaar { 2801c991144SBram Moolenaar emsg(_("E1046: Missing comma in import")); 2811c991144SBram Moolenaar goto erret; 2821c991144SBram Moolenaar } 2831c991144SBram Moolenaar } 2841c991144SBram Moolenaar if (names.ga_len == 0) 2851c991144SBram Moolenaar { 2861c991144SBram Moolenaar emsg(_(e_import_syntax)); 2871c991144SBram Moolenaar goto erret; 2881c991144SBram Moolenaar } 2898a7d6542SBram Moolenaar } 2908a7d6542SBram Moolenaar else 2918a7d6542SBram Moolenaar { 2921c991144SBram Moolenaar // "import Name from ..." 2931c991144SBram Moolenaar // "import * as Name from ..." 2941c991144SBram Moolenaar // "import item [as Name] from ..." 2951c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg, evalarg); 2961c991144SBram Moolenaar if (arg[0] == '*' && IS_WHITE_OR_NUL(arg[1])) 2971c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg + 1, evalarg); 298fa29c8abSBram Moolenaar else if (eval_isnamec1(*arg)) 2998a7d6542SBram Moolenaar { 3001c991144SBram Moolenaar char_u *p = arg; 3011c991144SBram Moolenaar 302fa29c8abSBram Moolenaar while (eval_isnamec(*arg)) 3038a7d6542SBram Moolenaar ++arg; 3041c991144SBram Moolenaar if (ga_grow(&names, 1) == FAIL) 3051c991144SBram Moolenaar goto erret; 3061c991144SBram Moolenaar ((char_u **)names.ga_data)[names.ga_len] = 3071c991144SBram Moolenaar vim_strnsave(p, arg - p); 3081c991144SBram Moolenaar ++names.ga_len; 3091c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg, evalarg); 3108a7d6542SBram Moolenaar } 3111c991144SBram Moolenaar else 3128a7d6542SBram Moolenaar { 3131c991144SBram Moolenaar emsg(_(e_import_syntax)); 3141c991144SBram Moolenaar goto erret; 3151c991144SBram Moolenaar } 3161c991144SBram Moolenaar 3171c991144SBram Moolenaar if (STRNCMP("as", arg, 2) == 0 && IS_WHITE_OR_NUL(arg[2])) 3181c991144SBram Moolenaar { 3191c991144SBram Moolenaar char_u *p; 3201c991144SBram Moolenaar 3211c991144SBram Moolenaar // skip over "as Name "; no line break allowed after "as" 3228a7d6542SBram Moolenaar arg = skipwhite(arg + 2); 3231c991144SBram Moolenaar p = arg; 324fa29c8abSBram Moolenaar if (eval_isnamec1(*arg)) 325fa29c8abSBram Moolenaar while (eval_isnamec(*arg)) 3268a7d6542SBram Moolenaar ++arg; 327*cbb6bdcdSBram Moolenaar if (check_defined(p, arg - p, cctx) == FAIL) 3281c991144SBram Moolenaar goto erret; 3291c991144SBram Moolenaar as_name = vim_strnsave(p, arg - p); 3301c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg, evalarg); 3318a7d6542SBram Moolenaar } 3328a7d6542SBram Moolenaar else if (*arg_start == '*') 3338a7d6542SBram Moolenaar { 3348a7d6542SBram Moolenaar emsg(_("E1045: Missing \"as\" after *")); 3351c991144SBram Moolenaar goto erret; 3368a7d6542SBram Moolenaar } 3378a7d6542SBram Moolenaar } 3381c991144SBram Moolenaar 3391c991144SBram Moolenaar if (STRNCMP("from", arg, 4) != 0 || !IS_WHITE_OR_NUL(arg[4])) 3408a7d6542SBram Moolenaar { 341fa29c8abSBram Moolenaar emsg(_("E1070: Missing \"from\"")); 3421c991144SBram Moolenaar goto erret; 3438a7d6542SBram Moolenaar } 3441c991144SBram Moolenaar 345962d7213SBram Moolenaar arg = skipwhite_and_linebreak(arg + 4, evalarg); 3468a7d6542SBram Moolenaar tv.v_type = VAR_UNKNOWN; 3478a7d6542SBram Moolenaar // TODO: should we accept any expression? 3488a7d6542SBram Moolenaar if (*arg == '\'') 3499a78e6dfSBram Moolenaar ret = eval_lit_string(&arg, &tv, TRUE); 3508a7d6542SBram Moolenaar else if (*arg == '"') 3519a78e6dfSBram Moolenaar ret = eval_string(&arg, &tv, TRUE); 3528a7d6542SBram Moolenaar if (ret == FAIL || tv.vval.v_string == NULL || *tv.vval.v_string == NUL) 3538a7d6542SBram Moolenaar { 354fa29c8abSBram Moolenaar emsg(_("E1071: Invalid string after \"from\"")); 3551c991144SBram Moolenaar goto erret; 3568a7d6542SBram Moolenaar } 3578a7d6542SBram Moolenaar cmd_end = arg; 3588a7d6542SBram Moolenaar 3591c991144SBram Moolenaar /* 3601c991144SBram Moolenaar * find script file 3611c991144SBram Moolenaar */ 3628a7d6542SBram Moolenaar if (*tv.vval.v_string == '.') 3638a7d6542SBram Moolenaar { 3648a7d6542SBram Moolenaar size_t len; 36521b9e977SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 3668a7d6542SBram Moolenaar char_u *tail = gettail(si->sn_name); 3678a7d6542SBram Moolenaar char_u *from_name; 3688a7d6542SBram Moolenaar 3698a7d6542SBram Moolenaar // Relative to current script: "./name.vim", "../../name.vim". 3708a7d6542SBram Moolenaar len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2; 3718a7d6542SBram Moolenaar from_name = alloc((int)len); 3728a7d6542SBram Moolenaar if (from_name == NULL) 3738a7d6542SBram Moolenaar { 3748a7d6542SBram Moolenaar clear_tv(&tv); 3751c991144SBram Moolenaar goto erret; 3768a7d6542SBram Moolenaar } 3778a7d6542SBram Moolenaar vim_strncpy(from_name, si->sn_name, tail - si->sn_name); 3788a7d6542SBram Moolenaar add_pathsep(from_name); 3798a7d6542SBram Moolenaar STRCAT(from_name, tv.vval.v_string); 3808a7d6542SBram Moolenaar simplify_filename(from_name); 3818a7d6542SBram Moolenaar 3828a7d6542SBram Moolenaar res = do_source(from_name, FALSE, DOSO_NONE, &sid); 3838a7d6542SBram Moolenaar vim_free(from_name); 3848a7d6542SBram Moolenaar } 3858a7d6542SBram Moolenaar else if (mch_isFullName(tv.vval.v_string)) 3868a7d6542SBram Moolenaar { 3878a7d6542SBram Moolenaar // Absolute path: "/tmp/name.vim" 3888a7d6542SBram Moolenaar res = do_source(tv.vval.v_string, FALSE, DOSO_NONE, &sid); 3898a7d6542SBram Moolenaar } 3908a7d6542SBram Moolenaar else 3918a7d6542SBram Moolenaar { 3928a7d6542SBram Moolenaar size_t len = 7 + STRLEN(tv.vval.v_string) + 1; 3938a7d6542SBram Moolenaar char_u *from_name; 3948a7d6542SBram Moolenaar 3958a7d6542SBram Moolenaar // Find file in "import" subdirs in 'runtimepath'. 3968a7d6542SBram Moolenaar from_name = alloc((int)len); 3978a7d6542SBram Moolenaar if (from_name == NULL) 3988a7d6542SBram Moolenaar { 3998a7d6542SBram Moolenaar clear_tv(&tv); 4001c991144SBram Moolenaar goto erret; 4018a7d6542SBram Moolenaar } 4028a7d6542SBram Moolenaar vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string); 4038a7d6542SBram Moolenaar res = source_in_path(p_rtp, from_name, DIP_NOAFTER, &sid); 4048a7d6542SBram Moolenaar vim_free(from_name); 4058a7d6542SBram Moolenaar } 4068a7d6542SBram Moolenaar 4078a7d6542SBram Moolenaar if (res == FAIL || sid <= 0) 4088a7d6542SBram Moolenaar { 4098a7d6542SBram Moolenaar semsg(_("E1053: Could not import \"%s\""), tv.vval.v_string); 4108a7d6542SBram Moolenaar clear_tv(&tv); 4111c991144SBram Moolenaar goto erret; 4128a7d6542SBram Moolenaar } 4138a7d6542SBram Moolenaar clear_tv(&tv); 4148a7d6542SBram Moolenaar 4158a7d6542SBram Moolenaar if (*arg_start == '*') 4168a7d6542SBram Moolenaar { 4178a7d6542SBram Moolenaar imported_T *imported = new_imported(gap != NULL ? gap 41821b9e977SBram Moolenaar : &SCRIPT_ITEM(import_sid)->sn_imports); 4198a7d6542SBram Moolenaar 4208a7d6542SBram Moolenaar if (imported == NULL) 4211c991144SBram Moolenaar goto erret; 4221c991144SBram Moolenaar imported->imp_name = as_name; 4231c991144SBram Moolenaar as_name = NULL; 4248a7d6542SBram Moolenaar imported->imp_sid = sid; 4258a7d6542SBram Moolenaar imported->imp_all = TRUE; 4268a7d6542SBram Moolenaar } 4278a7d6542SBram Moolenaar else 4288a7d6542SBram Moolenaar { 4291c991144SBram Moolenaar int i; 4301c991144SBram Moolenaar 4318a7d6542SBram Moolenaar arg = arg_start; 4328a7d6542SBram Moolenaar if (*arg == '{') 4338a7d6542SBram Moolenaar arg = skipwhite(arg + 1); 4341c991144SBram Moolenaar for (i = 0; i < names.ga_len; ++i) 4358a7d6542SBram Moolenaar { 4361c991144SBram Moolenaar char_u *name = ((char_u **)names.ga_data)[i]; 4378a7d6542SBram Moolenaar int idx; 4388a7d6542SBram Moolenaar imported_T *imported; 439f2d5c240SBram Moolenaar ufunc_T *ufunc = NULL; 440f2d5c240SBram Moolenaar type_T *type; 4418a7d6542SBram Moolenaar 4421c991144SBram Moolenaar idx = find_exported(sid, name, &ufunc, &type); 4438a7d6542SBram Moolenaar 444f2d5c240SBram Moolenaar if (idx < 0 && ufunc == NULL) 4451c991144SBram Moolenaar goto erret; 4468a7d6542SBram Moolenaar 4471c991144SBram Moolenaar if (check_defined(name, STRLEN(name), cctx) == FAIL) 4481c991144SBram Moolenaar goto erret; 4495269bd2aSBram Moolenaar 4508a7d6542SBram Moolenaar imported = new_imported(gap != NULL ? gap 45121b9e977SBram Moolenaar : &SCRIPT_ITEM(import_sid)->sn_imports); 4528a7d6542SBram Moolenaar if (imported == NULL) 4531c991144SBram Moolenaar goto erret; 4548a7d6542SBram Moolenaar 4558a7d6542SBram Moolenaar // TODO: check for "as" following 4561c991144SBram Moolenaar // imported->imp_name = vim_strsave(as_name); 4571c991144SBram Moolenaar imported->imp_name = name; 4581c991144SBram Moolenaar ((char_u **)names.ga_data)[i] = NULL; 4598a7d6542SBram Moolenaar imported->imp_sid = sid; 4608a7d6542SBram Moolenaar if (idx >= 0) 4618a7d6542SBram Moolenaar { 462f2d5c240SBram Moolenaar imported->imp_type = type; 4638a7d6542SBram Moolenaar imported->imp_var_vals_idx = idx; 4648a7d6542SBram Moolenaar } 4658a7d6542SBram Moolenaar else 4668a7d6542SBram Moolenaar imported->imp_funcname = ufunc->uf_name; 4678a7d6542SBram Moolenaar } 4688a7d6542SBram Moolenaar } 4691c991144SBram Moolenaar erret: 4701c991144SBram Moolenaar ga_clear_strings(&names); 4711c991144SBram Moolenaar vim_free(as_name); 4728a7d6542SBram Moolenaar return cmd_end; 4738a7d6542SBram Moolenaar } 4748a7d6542SBram Moolenaar 475c82a5b5dSBram Moolenaar /* 476c82a5b5dSBram Moolenaar * Declare a script-local variable without init: "let var: type". 477c82a5b5dSBram Moolenaar * "const" is an error since the value is missing. 478c82a5b5dSBram Moolenaar * Returns a pointer to after the type. 479c82a5b5dSBram Moolenaar */ 480c82a5b5dSBram Moolenaar char_u * 481c82a5b5dSBram Moolenaar vim9_declare_scriptvar(exarg_T *eap, char_u *arg) 482c82a5b5dSBram Moolenaar { 483c82a5b5dSBram Moolenaar char_u *p; 484c82a5b5dSBram Moolenaar char_u *name; 485c82a5b5dSBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 486c82a5b5dSBram Moolenaar type_T *type; 487c82a5b5dSBram Moolenaar int called_emsg_before = called_emsg; 488c82a5b5dSBram Moolenaar typval_T init_tv; 489c82a5b5dSBram Moolenaar 490c82a5b5dSBram Moolenaar if (eap->cmdidx == CMD_const) 491c82a5b5dSBram Moolenaar { 492c82a5b5dSBram Moolenaar emsg(_(e_const_req_value)); 493c82a5b5dSBram Moolenaar return arg + STRLEN(arg); 494c82a5b5dSBram Moolenaar } 495c82a5b5dSBram Moolenaar 496c82a5b5dSBram Moolenaar // Check for valid starting character. 497c82a5b5dSBram Moolenaar if (!eval_isnamec1(*arg)) 498c82a5b5dSBram Moolenaar { 499c82a5b5dSBram Moolenaar semsg(_(e_invarg2), arg); 500c82a5b5dSBram Moolenaar return arg + STRLEN(arg); 501c82a5b5dSBram Moolenaar } 502c82a5b5dSBram Moolenaar 503984dddbeSBram Moolenaar for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p)) 5043b74b6b4SBram Moolenaar if (*p == ':' && (VIM_ISWHITE(p[1]) || p != arg + 1)) 505984dddbeSBram Moolenaar break; 506c82a5b5dSBram Moolenaar 507c82a5b5dSBram Moolenaar if (*p != ':') 508c82a5b5dSBram Moolenaar { 509c82a5b5dSBram Moolenaar emsg(_(e_type_req)); 510c82a5b5dSBram Moolenaar return arg + STRLEN(arg); 511c82a5b5dSBram Moolenaar } 512984dddbeSBram Moolenaar if (!VIM_ISWHITE(p[1])) 513984dddbeSBram Moolenaar { 514984dddbeSBram Moolenaar semsg(_(e_white_after), ":"); 515984dddbeSBram Moolenaar return arg + STRLEN(arg); 516984dddbeSBram Moolenaar } 517c82a5b5dSBram Moolenaar name = vim_strnsave(arg, p - arg); 518c82a5b5dSBram Moolenaar 519c82a5b5dSBram Moolenaar // parse type 520c82a5b5dSBram Moolenaar p = skipwhite(p + 1); 521c82a5b5dSBram Moolenaar type = parse_type(&p, &si->sn_type_list); 522c82a5b5dSBram Moolenaar if (called_emsg != called_emsg_before) 523f3decc58SBram Moolenaar { 524f3decc58SBram Moolenaar vim_free(name); 525c82a5b5dSBram Moolenaar return p; 526f3decc58SBram Moolenaar } 527c82a5b5dSBram Moolenaar 528c82a5b5dSBram Moolenaar // Create the variable with 0/NULL value. 529c82a5b5dSBram Moolenaar CLEAR_FIELD(init_tv); 530c82a5b5dSBram Moolenaar init_tv.v_type = type->tt_type; 531c82a5b5dSBram Moolenaar set_var_const(name, type, &init_tv, FALSE, 0); 532c82a5b5dSBram Moolenaar 533c82a5b5dSBram Moolenaar vim_free(name); 534c82a5b5dSBram Moolenaar return p; 535c82a5b5dSBram Moolenaar } 536c82a5b5dSBram Moolenaar 53734db91f7SBram Moolenaar /* 53834db91f7SBram Moolenaar * Check if the type of script variable "dest" allows assigning "value". 53934db91f7SBram Moolenaar */ 540c785b9a7SBram Moolenaar int 54134db91f7SBram Moolenaar check_script_var_type(typval_T *dest, typval_T *value, char_u *name) 54234db91f7SBram Moolenaar { 54334db91f7SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 54434db91f7SBram Moolenaar int idx; 54534db91f7SBram Moolenaar 54634db91f7SBram Moolenaar // Find the svar_T in sn_var_vals. 54734db91f7SBram Moolenaar for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx) 54834db91f7SBram Moolenaar { 54934db91f7SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; 55034db91f7SBram Moolenaar 55134db91f7SBram Moolenaar if (sv->sv_tv == dest) 55234db91f7SBram Moolenaar { 55334db91f7SBram Moolenaar if (sv->sv_const) 554c785b9a7SBram Moolenaar { 55534db91f7SBram Moolenaar semsg(_(e_readonlyvar), name); 556c785b9a7SBram Moolenaar return FAIL; 557c785b9a7SBram Moolenaar } 558c785b9a7SBram Moolenaar return check_type(sv->sv_type, typval2type(value), TRUE); 55934db91f7SBram Moolenaar } 56034db91f7SBram Moolenaar } 56134db91f7SBram Moolenaar iemsg("check_script_var_type(): not found"); 562c785b9a7SBram Moolenaar return OK; // not really 56334db91f7SBram Moolenaar } 564c82a5b5dSBram Moolenaar 5658a7d6542SBram Moolenaar #endif // FEAT_EVAL 566