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 { 25eb6880b6SBram Moolenaar // Do not go up the stack, a ":function" inside vim9script uses legacy 26eb6880b6SBram Moolenaar // syntax. "sc_version" is also set when compiling a ":def" function in 27eb6880b6SBram Moolenaar // legacy script. 288a7d6542SBram Moolenaar return current_sctx.sc_version == SCRIPT_VERSION_VIM9; 298a7d6542SBram Moolenaar } 308a7d6542SBram Moolenaar 318a7d6542SBram Moolenaar /* 328a7d6542SBram Moolenaar * ":vim9script". 338a7d6542SBram Moolenaar */ 348a7d6542SBram Moolenaar void 358a7d6542SBram Moolenaar ex_vim9script(exarg_T *eap) 368a7d6542SBram Moolenaar { 37101f4810SBram Moolenaar scriptitem_T *si; 388a7d6542SBram Moolenaar 398a7d6542SBram Moolenaar if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 408a7d6542SBram Moolenaar { 418a7d6542SBram Moolenaar emsg(_("E1038: vim9script can only be used in a script")); 428a7d6542SBram Moolenaar return; 438a7d6542SBram Moolenaar } 44101f4810SBram Moolenaar si = SCRIPT_ITEM(current_sctx.sc_sid); 458a7d6542SBram Moolenaar if (si->sn_had_command) 468a7d6542SBram Moolenaar { 478a7d6542SBram Moolenaar emsg(_("E1039: vim9script must be the first command in a script")); 488a7d6542SBram Moolenaar return; 498a7d6542SBram Moolenaar } 508a7d6542SBram Moolenaar current_sctx.sc_version = SCRIPT_VERSION_VIM9; 518a7d6542SBram Moolenaar si->sn_version = SCRIPT_VERSION_VIM9; 528a7d6542SBram Moolenaar si->sn_had_command = TRUE; 538a7d6542SBram Moolenaar 548a7d6542SBram Moolenaar if (STRCMP(p_cpo, CPO_VIM) != 0) 558a7d6542SBram Moolenaar { 568a7d6542SBram Moolenaar si->sn_save_cpo = p_cpo; 578a7d6542SBram Moolenaar p_cpo = vim_strsave((char_u *)CPO_VIM); 588a7d6542SBram Moolenaar } 59227a69deSBram Moolenaar } 608a7d6542SBram Moolenaar 618a7d6542SBram Moolenaar /* 628a7d6542SBram Moolenaar * ":export let Name: type" 638a7d6542SBram Moolenaar * ":export const Name: type" 648a7d6542SBram Moolenaar * ":export def Name(..." 658a7d6542SBram Moolenaar * ":export class Name ..." 668a7d6542SBram Moolenaar * 678a7d6542SBram Moolenaar * ":export {Name, ...}" 688a7d6542SBram Moolenaar */ 698a7d6542SBram Moolenaar void 7009689a02SBram Moolenaar ex_export(exarg_T *eap) 718a7d6542SBram Moolenaar { 72eb6880b6SBram Moolenaar if (!in_vim9script()) 738a7d6542SBram Moolenaar { 748a7d6542SBram Moolenaar emsg(_(e_needs_vim9)); 758a7d6542SBram Moolenaar return; 768a7d6542SBram Moolenaar } 778a7d6542SBram Moolenaar 788a7d6542SBram Moolenaar eap->cmd = eap->arg; 798a7d6542SBram Moolenaar (void)find_ex_command(eap, NULL, lookup_scriptvar, NULL); 808a7d6542SBram Moolenaar switch (eap->cmdidx) 818a7d6542SBram Moolenaar { 828a7d6542SBram Moolenaar case CMD_let: 838a7d6542SBram Moolenaar case CMD_const: 848a7d6542SBram Moolenaar case CMD_def: 858a7d6542SBram Moolenaar // case CMD_class: 868a7d6542SBram Moolenaar is_export = TRUE; 878a7d6542SBram Moolenaar do_cmdline(eap->cmd, eap->getline, eap->cookie, 888a7d6542SBram Moolenaar DOCMD_VERBOSE + DOCMD_NOWAIT); 898a7d6542SBram Moolenaar 908a7d6542SBram Moolenaar // The command will reset "is_export" when exporting an item. 918a7d6542SBram Moolenaar if (is_export) 928a7d6542SBram Moolenaar { 938a7d6542SBram Moolenaar emsg(_("E1044: export with invalid argument")); 948a7d6542SBram Moolenaar is_export = FALSE; 958a7d6542SBram Moolenaar } 968a7d6542SBram Moolenaar break; 978a7d6542SBram Moolenaar default: 988a7d6542SBram Moolenaar emsg(_("E1043: Invalid command after :export")); 998a7d6542SBram Moolenaar break; 1008a7d6542SBram Moolenaar } 1018a7d6542SBram Moolenaar } 1028a7d6542SBram Moolenaar 1038a7d6542SBram Moolenaar /* 1048a7d6542SBram Moolenaar * Add a new imported item entry to the current script. 1058a7d6542SBram Moolenaar */ 1068a7d6542SBram Moolenaar static imported_T * 1078a7d6542SBram Moolenaar new_imported(garray_T *gap) 1088a7d6542SBram Moolenaar { 1098a7d6542SBram Moolenaar if (ga_grow(gap, 1) == OK) 1108a7d6542SBram Moolenaar return ((imported_T *)gap->ga_data + gap->ga_len++); 1118a7d6542SBram Moolenaar return NULL; 1128a7d6542SBram Moolenaar } 1138a7d6542SBram Moolenaar 1148a7d6542SBram Moolenaar /* 1158a7d6542SBram Moolenaar * Free all imported items in script "sid". 1168a7d6542SBram Moolenaar */ 1178a7d6542SBram Moolenaar void 1188a7d6542SBram Moolenaar free_imports(int sid) 1198a7d6542SBram Moolenaar { 12021b9e977SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(sid); 1218a7d6542SBram Moolenaar int idx; 1228a7d6542SBram Moolenaar 1238a7d6542SBram Moolenaar for (idx = 0; idx < si->sn_imports.ga_len; ++idx) 1248a7d6542SBram Moolenaar { 12520431c9dSBram Moolenaar imported_T *imp = ((imported_T *)si->sn_imports.ga_data) + idx; 1268a7d6542SBram Moolenaar 1278a7d6542SBram Moolenaar vim_free(imp->imp_name); 1288a7d6542SBram Moolenaar } 1298a7d6542SBram Moolenaar ga_clear(&si->sn_imports); 13020431c9dSBram Moolenaar ga_clear(&si->sn_var_vals); 1316110e79aSBram Moolenaar clear_type_list(&si->sn_type_list); 1328a7d6542SBram Moolenaar } 1338a7d6542SBram Moolenaar 1348a7d6542SBram Moolenaar /* 1358a7d6542SBram Moolenaar * ":import Item from 'filename'" 1368a7d6542SBram Moolenaar * ":import Item as Alias from 'filename'" 1378a7d6542SBram Moolenaar * ":import {Item} from 'filename'". 1388a7d6542SBram Moolenaar * ":import {Item as Alias} from 'filename'" 1398a7d6542SBram Moolenaar * ":import {Item, Item} from 'filename'" 1408a7d6542SBram Moolenaar * ":import {Item, Item as Alias} from 'filename'" 1418a7d6542SBram Moolenaar * 1428a7d6542SBram Moolenaar * ":import * as Name from 'filename'" 1438a7d6542SBram Moolenaar */ 1448a7d6542SBram Moolenaar void 1458a7d6542SBram Moolenaar ex_import(exarg_T *eap) 1468a7d6542SBram Moolenaar { 147101f4810SBram Moolenaar char_u *cmd_end; 1481c991144SBram Moolenaar evalarg_T evalarg; 1498a7d6542SBram Moolenaar 150101f4810SBram Moolenaar if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 151101f4810SBram Moolenaar { 152101f4810SBram Moolenaar emsg(_("E1094: import can only be used in a script")); 153101f4810SBram Moolenaar return; 154101f4810SBram Moolenaar } 1551c991144SBram Moolenaar fill_evalarg_from_eap(&evalarg, eap, eap->skip); 156101f4810SBram Moolenaar 1571c991144SBram Moolenaar cmd_end = handle_import(eap->arg, NULL, current_sctx.sc_sid, 1581c991144SBram Moolenaar &evalarg, NULL); 1598a7d6542SBram Moolenaar if (cmd_end != NULL) 1608a7d6542SBram Moolenaar eap->nextcmd = check_nextcmd(cmd_end); 1611c991144SBram Moolenaar clear_evalarg(&evalarg, eap); 1628a7d6542SBram Moolenaar } 1638a7d6542SBram Moolenaar 1648a7d6542SBram Moolenaar /* 165f2d5c240SBram Moolenaar * Find an exported item in "sid" matching the name at "*argp". 166f2d5c240SBram Moolenaar * When it is a variable return the index. 167f2d5c240SBram Moolenaar * When it is a user function return "*ufunc". 168f2d5c240SBram Moolenaar * When not found returns -1 and "*ufunc" is NULL. 169f2d5c240SBram Moolenaar */ 170f2d5c240SBram Moolenaar int 171f2d5c240SBram Moolenaar find_exported( 172f2d5c240SBram Moolenaar int sid, 1731c991144SBram Moolenaar char_u *name, 174f2d5c240SBram Moolenaar ufunc_T **ufunc, 175f2d5c240SBram Moolenaar type_T **type) 176f2d5c240SBram Moolenaar { 177f2d5c240SBram Moolenaar int idx = -1; 178f2d5c240SBram Moolenaar svar_T *sv; 179f2d5c240SBram Moolenaar scriptitem_T *script = SCRIPT_ITEM(sid); 180f2d5c240SBram Moolenaar 181f2d5c240SBram Moolenaar // find name in "script" 182f2d5c240SBram Moolenaar // TODO: also find script-local user function 183f2d5c240SBram Moolenaar idx = get_script_item_idx(sid, name, FALSE); 184f2d5c240SBram Moolenaar if (idx >= 0) 185f2d5c240SBram Moolenaar { 186f2d5c240SBram Moolenaar sv = ((svar_T *)script->sn_var_vals.ga_data) + idx; 187f2d5c240SBram Moolenaar if (!sv->sv_export) 188f2d5c240SBram Moolenaar { 189f2d5c240SBram Moolenaar semsg(_("E1049: Item not exported in script: %s"), name); 190f2d5c240SBram Moolenaar return -1; 191f2d5c240SBram Moolenaar } 192f2d5c240SBram Moolenaar *type = sv->sv_type; 193f2d5c240SBram Moolenaar *ufunc = NULL; 194f2d5c240SBram Moolenaar } 195f2d5c240SBram Moolenaar else 196f2d5c240SBram Moolenaar { 197f2d5c240SBram Moolenaar char_u buffer[200]; 198f2d5c240SBram Moolenaar char_u *funcname; 199f2d5c240SBram Moolenaar 200f2d5c240SBram Moolenaar // it could be a user function. 201f2d5c240SBram Moolenaar if (STRLEN(name) < sizeof(buffer) - 10) 202f2d5c240SBram Moolenaar funcname = buffer; 203f2d5c240SBram Moolenaar else 204f2d5c240SBram Moolenaar { 205f2d5c240SBram Moolenaar funcname = alloc(STRLEN(name) + 10); 206f2d5c240SBram Moolenaar if (funcname == NULL) 207f2d5c240SBram Moolenaar return -1; 208f2d5c240SBram Moolenaar } 209f2d5c240SBram Moolenaar funcname[0] = K_SPECIAL; 210f2d5c240SBram Moolenaar funcname[1] = KS_EXTRA; 211f2d5c240SBram Moolenaar funcname[2] = (int)KE_SNR; 212f2d5c240SBram Moolenaar sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name); 2134c17ad94SBram Moolenaar *ufunc = find_func(funcname, FALSE, NULL); 214f2d5c240SBram Moolenaar if (funcname != buffer) 215f2d5c240SBram Moolenaar vim_free(funcname); 216f2d5c240SBram Moolenaar 217f2d5c240SBram Moolenaar if (*ufunc == NULL) 218f2d5c240SBram Moolenaar { 219f2d5c240SBram Moolenaar semsg(_("E1048: Item not found in script: %s"), name); 220f2d5c240SBram Moolenaar return -1; 221f2d5c240SBram Moolenaar } 222f2d5c240SBram Moolenaar } 223f2d5c240SBram Moolenaar 224f2d5c240SBram Moolenaar return idx; 225f2d5c240SBram Moolenaar } 226f2d5c240SBram Moolenaar 227f2d5c240SBram Moolenaar /* 2288a7d6542SBram Moolenaar * Handle an ":import" command and add the resulting imported_T to "gap", when 2298a7d6542SBram Moolenaar * not NULL, or script "import_sid" sn_imports. 2308a7d6542SBram Moolenaar * Returns a pointer to after the command or NULL in case of failure 2318a7d6542SBram Moolenaar */ 2328a7d6542SBram Moolenaar char_u * 2331c991144SBram Moolenaar handle_import( 2341c991144SBram Moolenaar char_u *arg_start, 2351c991144SBram Moolenaar garray_T *gap, 2361c991144SBram Moolenaar int import_sid, 2371c991144SBram Moolenaar evalarg_T *evalarg, 2381c991144SBram Moolenaar void *cctx) 2398a7d6542SBram Moolenaar { 2408a7d6542SBram Moolenaar char_u *arg = arg_start; 2411c991144SBram Moolenaar char_u *cmd_end = NULL; 2421c991144SBram Moolenaar char_u *as_name = NULL; 2438a7d6542SBram Moolenaar int ret = FAIL; 2448a7d6542SBram Moolenaar typval_T tv; 2458a7d6542SBram Moolenaar int sid = -1; 2468a7d6542SBram Moolenaar int res; 2471c991144SBram Moolenaar garray_T names; 2481c991144SBram Moolenaar static char e_import_syntax[] = N_("E1047: syntax error in import"); 2498a7d6542SBram Moolenaar 2501c991144SBram Moolenaar ga_init2(&names, sizeof(char_u *), 10); 2518a7d6542SBram Moolenaar if (*arg == '{') 2528a7d6542SBram Moolenaar { 2531c991144SBram Moolenaar // "import {item, item} from ..." 2541c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg + 1, evalarg); 2551c991144SBram Moolenaar for (;;) 2561c991144SBram Moolenaar { 2571c991144SBram Moolenaar char_u *p = arg; 2581c991144SBram Moolenaar int had_comma = FALSE; 2591c991144SBram Moolenaar 2601c991144SBram Moolenaar while (eval_isnamec(*arg)) 2618a7d6542SBram Moolenaar ++arg; 2621c991144SBram Moolenaar if (p == arg) 2631c991144SBram Moolenaar break; 2641c991144SBram Moolenaar if (ga_grow(&names, 1) == FAIL) 2651c991144SBram Moolenaar goto erret; 2661c991144SBram Moolenaar ((char_u **)names.ga_data)[names.ga_len] = 2671c991144SBram Moolenaar vim_strnsave(p, arg - p); 2681c991144SBram Moolenaar ++names.ga_len; 2691c991144SBram Moolenaar if (*arg == ',') 2701c991144SBram Moolenaar { 2711c991144SBram Moolenaar had_comma = TRUE; 2721c991144SBram Moolenaar ++arg; 2731c991144SBram Moolenaar } 2741c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg, evalarg); 2758a7d6542SBram Moolenaar if (*arg == '}') 2761c991144SBram Moolenaar { 2771c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg + 1, evalarg); 2781c991144SBram Moolenaar break; 2791c991144SBram Moolenaar } 2801c991144SBram Moolenaar if (!had_comma) 2811c991144SBram Moolenaar { 2821c991144SBram Moolenaar emsg(_("E1046: Missing comma in import")); 2831c991144SBram Moolenaar goto erret; 2841c991144SBram Moolenaar } 2851c991144SBram Moolenaar } 2861c991144SBram Moolenaar if (names.ga_len == 0) 2871c991144SBram Moolenaar { 2881c991144SBram Moolenaar emsg(_(e_import_syntax)); 2891c991144SBram Moolenaar goto erret; 2901c991144SBram Moolenaar } 2918a7d6542SBram Moolenaar } 2928a7d6542SBram Moolenaar else 2938a7d6542SBram Moolenaar { 2941c991144SBram Moolenaar // "import Name from ..." 2951c991144SBram Moolenaar // "import * as Name from ..." 2961c991144SBram Moolenaar // "import item [as Name] from ..." 2971c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg, evalarg); 2981c991144SBram Moolenaar if (arg[0] == '*' && IS_WHITE_OR_NUL(arg[1])) 2991c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg + 1, evalarg); 300fa29c8abSBram Moolenaar else if (eval_isnamec1(*arg)) 3018a7d6542SBram Moolenaar { 3021c991144SBram Moolenaar char_u *p = arg; 3031c991144SBram Moolenaar 304fa29c8abSBram Moolenaar while (eval_isnamec(*arg)) 3058a7d6542SBram Moolenaar ++arg; 3061c991144SBram Moolenaar if (ga_grow(&names, 1) == FAIL) 3071c991144SBram Moolenaar goto erret; 3081c991144SBram Moolenaar ((char_u **)names.ga_data)[names.ga_len] = 3091c991144SBram Moolenaar vim_strnsave(p, arg - p); 3101c991144SBram Moolenaar ++names.ga_len; 3111c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg, evalarg); 3128a7d6542SBram Moolenaar } 3131c991144SBram Moolenaar else 3148a7d6542SBram Moolenaar { 3151c991144SBram Moolenaar emsg(_(e_import_syntax)); 3161c991144SBram Moolenaar goto erret; 3171c991144SBram Moolenaar } 3181c991144SBram Moolenaar 3191c991144SBram Moolenaar if (STRNCMP("as", arg, 2) == 0 && IS_WHITE_OR_NUL(arg[2])) 3201c991144SBram Moolenaar { 3211c991144SBram Moolenaar char_u *p; 3221c991144SBram Moolenaar 3231c991144SBram Moolenaar // skip over "as Name "; no line break allowed after "as" 3248a7d6542SBram Moolenaar arg = skipwhite(arg + 2); 3251c991144SBram Moolenaar p = arg; 326fa29c8abSBram Moolenaar if (eval_isnamec1(*arg)) 327fa29c8abSBram Moolenaar while (eval_isnamec(*arg)) 3288a7d6542SBram Moolenaar ++arg; 329cbb6bdcdSBram Moolenaar if (check_defined(p, arg - p, cctx) == FAIL) 3301c991144SBram Moolenaar goto erret; 3311c991144SBram Moolenaar as_name = vim_strnsave(p, arg - p); 3321c991144SBram Moolenaar arg = skipwhite_and_linebreak(arg, evalarg); 3338a7d6542SBram Moolenaar } 3348a7d6542SBram Moolenaar else if (*arg_start == '*') 3358a7d6542SBram Moolenaar { 3368a7d6542SBram Moolenaar emsg(_("E1045: Missing \"as\" after *")); 3371c991144SBram Moolenaar goto erret; 3388a7d6542SBram Moolenaar } 3398a7d6542SBram Moolenaar } 3401c991144SBram Moolenaar 3411c991144SBram Moolenaar if (STRNCMP("from", arg, 4) != 0 || !IS_WHITE_OR_NUL(arg[4])) 3428a7d6542SBram Moolenaar { 343fa29c8abSBram Moolenaar emsg(_("E1070: Missing \"from\"")); 3441c991144SBram Moolenaar goto erret; 3458a7d6542SBram Moolenaar } 3461c991144SBram Moolenaar 347962d7213SBram Moolenaar arg = skipwhite_and_linebreak(arg + 4, evalarg); 3488a7d6542SBram Moolenaar tv.v_type = VAR_UNKNOWN; 3498a7d6542SBram Moolenaar // TODO: should we accept any expression? 3508a7d6542SBram Moolenaar if (*arg == '\'') 3519a78e6dfSBram Moolenaar ret = eval_lit_string(&arg, &tv, TRUE); 3528a7d6542SBram Moolenaar else if (*arg == '"') 3539a78e6dfSBram Moolenaar ret = eval_string(&arg, &tv, TRUE); 3548a7d6542SBram Moolenaar if (ret == FAIL || tv.vval.v_string == NULL || *tv.vval.v_string == NUL) 3558a7d6542SBram Moolenaar { 356fa29c8abSBram Moolenaar emsg(_("E1071: Invalid string after \"from\"")); 3571c991144SBram Moolenaar goto erret; 3588a7d6542SBram Moolenaar } 3598a7d6542SBram Moolenaar cmd_end = arg; 3608a7d6542SBram Moolenaar 3611c991144SBram Moolenaar /* 3621c991144SBram Moolenaar * find script file 3631c991144SBram Moolenaar */ 3648a7d6542SBram Moolenaar if (*tv.vval.v_string == '.') 3658a7d6542SBram Moolenaar { 3668a7d6542SBram Moolenaar size_t len; 36721b9e977SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 3688a7d6542SBram Moolenaar char_u *tail = gettail(si->sn_name); 3698a7d6542SBram Moolenaar char_u *from_name; 3708a7d6542SBram Moolenaar 3718a7d6542SBram Moolenaar // Relative to current script: "./name.vim", "../../name.vim". 3728a7d6542SBram Moolenaar len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2; 3738a7d6542SBram Moolenaar from_name = alloc((int)len); 3748a7d6542SBram Moolenaar if (from_name == NULL) 3758a7d6542SBram Moolenaar { 3768a7d6542SBram Moolenaar clear_tv(&tv); 3771c991144SBram Moolenaar goto erret; 3788a7d6542SBram Moolenaar } 3798a7d6542SBram Moolenaar vim_strncpy(from_name, si->sn_name, tail - si->sn_name); 3808a7d6542SBram Moolenaar add_pathsep(from_name); 3818a7d6542SBram Moolenaar STRCAT(from_name, tv.vval.v_string); 3828a7d6542SBram Moolenaar simplify_filename(from_name); 3838a7d6542SBram Moolenaar 3848a7d6542SBram Moolenaar res = do_source(from_name, FALSE, DOSO_NONE, &sid); 3858a7d6542SBram Moolenaar vim_free(from_name); 3868a7d6542SBram Moolenaar } 3878a7d6542SBram Moolenaar else if (mch_isFullName(tv.vval.v_string)) 3888a7d6542SBram Moolenaar { 3898a7d6542SBram Moolenaar // Absolute path: "/tmp/name.vim" 3908a7d6542SBram Moolenaar res = do_source(tv.vval.v_string, FALSE, DOSO_NONE, &sid); 3918a7d6542SBram Moolenaar } 3928a7d6542SBram Moolenaar else 3938a7d6542SBram Moolenaar { 3948a7d6542SBram Moolenaar size_t len = 7 + STRLEN(tv.vval.v_string) + 1; 3958a7d6542SBram Moolenaar char_u *from_name; 3968a7d6542SBram Moolenaar 3978a7d6542SBram Moolenaar // Find file in "import" subdirs in 'runtimepath'. 3988a7d6542SBram Moolenaar from_name = alloc((int)len); 3998a7d6542SBram Moolenaar if (from_name == NULL) 4008a7d6542SBram Moolenaar { 4018a7d6542SBram Moolenaar clear_tv(&tv); 4021c991144SBram Moolenaar goto erret; 4038a7d6542SBram Moolenaar } 4048a7d6542SBram Moolenaar vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string); 4058a7d6542SBram Moolenaar res = source_in_path(p_rtp, from_name, DIP_NOAFTER, &sid); 4068a7d6542SBram Moolenaar vim_free(from_name); 4078a7d6542SBram Moolenaar } 4088a7d6542SBram Moolenaar 4098a7d6542SBram Moolenaar if (res == FAIL || sid <= 0) 4108a7d6542SBram Moolenaar { 4118a7d6542SBram Moolenaar semsg(_("E1053: Could not import \"%s\""), tv.vval.v_string); 4128a7d6542SBram Moolenaar clear_tv(&tv); 4131c991144SBram Moolenaar goto erret; 4148a7d6542SBram Moolenaar } 4158a7d6542SBram Moolenaar clear_tv(&tv); 4168a7d6542SBram Moolenaar 4178a7d6542SBram Moolenaar if (*arg_start == '*') 4188a7d6542SBram Moolenaar { 4198a7d6542SBram Moolenaar imported_T *imported = new_imported(gap != NULL ? gap 42021b9e977SBram Moolenaar : &SCRIPT_ITEM(import_sid)->sn_imports); 4218a7d6542SBram Moolenaar 4228a7d6542SBram Moolenaar if (imported == NULL) 4231c991144SBram Moolenaar goto erret; 4241c991144SBram Moolenaar imported->imp_name = as_name; 4251c991144SBram Moolenaar as_name = NULL; 4268a7d6542SBram Moolenaar imported->imp_sid = sid; 4278a7d6542SBram Moolenaar imported->imp_all = TRUE; 4288a7d6542SBram Moolenaar } 4298a7d6542SBram Moolenaar else 4308a7d6542SBram Moolenaar { 4311c991144SBram Moolenaar int i; 4321c991144SBram Moolenaar 4338a7d6542SBram Moolenaar arg = arg_start; 4348a7d6542SBram Moolenaar if (*arg == '{') 4358a7d6542SBram Moolenaar arg = skipwhite(arg + 1); 4361c991144SBram Moolenaar for (i = 0; i < names.ga_len; ++i) 4378a7d6542SBram Moolenaar { 4381c991144SBram Moolenaar char_u *name = ((char_u **)names.ga_data)[i]; 4398a7d6542SBram Moolenaar int idx; 4408a7d6542SBram Moolenaar imported_T *imported; 441f2d5c240SBram Moolenaar ufunc_T *ufunc = NULL; 442f2d5c240SBram Moolenaar type_T *type; 4438a7d6542SBram Moolenaar 4441c991144SBram Moolenaar idx = find_exported(sid, name, &ufunc, &type); 4458a7d6542SBram Moolenaar 446f2d5c240SBram Moolenaar if (idx < 0 && ufunc == NULL) 4471c991144SBram Moolenaar goto erret; 4488a7d6542SBram Moolenaar 4491c991144SBram Moolenaar if (check_defined(name, STRLEN(name), cctx) == FAIL) 4501c991144SBram Moolenaar goto erret; 4515269bd2aSBram Moolenaar 4528a7d6542SBram Moolenaar imported = new_imported(gap != NULL ? gap 45321b9e977SBram Moolenaar : &SCRIPT_ITEM(import_sid)->sn_imports); 4548a7d6542SBram Moolenaar if (imported == NULL) 4551c991144SBram Moolenaar goto erret; 4568a7d6542SBram Moolenaar 4578a7d6542SBram Moolenaar // TODO: check for "as" following 4581c991144SBram Moolenaar // imported->imp_name = vim_strsave(as_name); 4591c991144SBram Moolenaar imported->imp_name = name; 4601c991144SBram Moolenaar ((char_u **)names.ga_data)[i] = NULL; 4618a7d6542SBram Moolenaar imported->imp_sid = sid; 4628a7d6542SBram Moolenaar if (idx >= 0) 4638a7d6542SBram Moolenaar { 464f2d5c240SBram Moolenaar imported->imp_type = type; 4658a7d6542SBram Moolenaar imported->imp_var_vals_idx = idx; 4668a7d6542SBram Moolenaar } 4678a7d6542SBram Moolenaar else 4688a7d6542SBram Moolenaar imported->imp_funcname = ufunc->uf_name; 4698a7d6542SBram Moolenaar } 4708a7d6542SBram Moolenaar } 4711c991144SBram Moolenaar erret: 4721c991144SBram Moolenaar ga_clear_strings(&names); 4731c991144SBram Moolenaar vim_free(as_name); 4748a7d6542SBram Moolenaar return cmd_end; 4758a7d6542SBram Moolenaar } 4768a7d6542SBram Moolenaar 477c82a5b5dSBram Moolenaar /* 478c82a5b5dSBram Moolenaar * Declare a script-local variable without init: "let var: type". 479c82a5b5dSBram Moolenaar * "const" is an error since the value is missing. 480c82a5b5dSBram Moolenaar * Returns a pointer to after the type. 481c82a5b5dSBram Moolenaar */ 482c82a5b5dSBram Moolenaar char_u * 483c82a5b5dSBram Moolenaar vim9_declare_scriptvar(exarg_T *eap, char_u *arg) 484c82a5b5dSBram Moolenaar { 485c82a5b5dSBram Moolenaar char_u *p; 486c82a5b5dSBram Moolenaar char_u *name; 487c82a5b5dSBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 488c82a5b5dSBram Moolenaar type_T *type; 489c82a5b5dSBram Moolenaar int called_emsg_before = called_emsg; 490c82a5b5dSBram Moolenaar typval_T init_tv; 491c82a5b5dSBram Moolenaar 492c82a5b5dSBram Moolenaar if (eap->cmdidx == CMD_const) 493c82a5b5dSBram Moolenaar { 494c82a5b5dSBram Moolenaar emsg(_(e_const_req_value)); 495c82a5b5dSBram Moolenaar return arg + STRLEN(arg); 496c82a5b5dSBram Moolenaar } 497c82a5b5dSBram Moolenaar 498c82a5b5dSBram Moolenaar // Check for valid starting character. 499c82a5b5dSBram Moolenaar if (!eval_isnamec1(*arg)) 500c82a5b5dSBram Moolenaar { 501c82a5b5dSBram Moolenaar semsg(_(e_invarg2), arg); 502c82a5b5dSBram Moolenaar return arg + STRLEN(arg); 503c82a5b5dSBram Moolenaar } 504c82a5b5dSBram Moolenaar 505984dddbeSBram Moolenaar for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p)) 5063b74b6b4SBram Moolenaar if (*p == ':' && (VIM_ISWHITE(p[1]) || p != arg + 1)) 507984dddbeSBram Moolenaar break; 508c82a5b5dSBram Moolenaar 509c82a5b5dSBram Moolenaar if (*p != ':') 510c82a5b5dSBram Moolenaar { 511c82a5b5dSBram Moolenaar emsg(_(e_type_req)); 512c82a5b5dSBram Moolenaar return arg + STRLEN(arg); 513c82a5b5dSBram Moolenaar } 514984dddbeSBram Moolenaar if (!VIM_ISWHITE(p[1])) 515984dddbeSBram Moolenaar { 516984dddbeSBram Moolenaar semsg(_(e_white_after), ":"); 517984dddbeSBram Moolenaar return arg + STRLEN(arg); 518984dddbeSBram Moolenaar } 519c82a5b5dSBram Moolenaar name = vim_strnsave(arg, p - arg); 520c82a5b5dSBram Moolenaar 521c82a5b5dSBram Moolenaar // parse type 522c82a5b5dSBram Moolenaar p = skipwhite(p + 1); 523c82a5b5dSBram Moolenaar type = parse_type(&p, &si->sn_type_list); 524c82a5b5dSBram Moolenaar if (called_emsg != called_emsg_before) 525f3decc58SBram Moolenaar { 526f3decc58SBram Moolenaar vim_free(name); 527c82a5b5dSBram Moolenaar return p; 528f3decc58SBram Moolenaar } 529c82a5b5dSBram Moolenaar 530c82a5b5dSBram Moolenaar // Create the variable with 0/NULL value. 531c82a5b5dSBram Moolenaar CLEAR_FIELD(init_tv); 532c82a5b5dSBram Moolenaar init_tv.v_type = type->tt_type; 533c82a5b5dSBram Moolenaar set_var_const(name, type, &init_tv, FALSE, 0); 534c82a5b5dSBram Moolenaar 535c82a5b5dSBram Moolenaar vim_free(name); 536c82a5b5dSBram Moolenaar return p; 537c82a5b5dSBram Moolenaar } 538c82a5b5dSBram Moolenaar 53934db91f7SBram Moolenaar /* 54034db91f7SBram Moolenaar * Check if the type of script variable "dest" allows assigning "value". 54134db91f7SBram Moolenaar */ 542c785b9a7SBram Moolenaar int 54334db91f7SBram Moolenaar check_script_var_type(typval_T *dest, typval_T *value, char_u *name) 54434db91f7SBram Moolenaar { 54534db91f7SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 54634db91f7SBram Moolenaar int idx; 54734db91f7SBram Moolenaar 54834db91f7SBram Moolenaar // Find the svar_T in sn_var_vals. 54934db91f7SBram Moolenaar for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx) 55034db91f7SBram Moolenaar { 55134db91f7SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; 55234db91f7SBram Moolenaar 55334db91f7SBram Moolenaar if (sv->sv_tv == dest) 55434db91f7SBram Moolenaar { 55534db91f7SBram Moolenaar if (sv->sv_const) 556c785b9a7SBram Moolenaar { 55734db91f7SBram Moolenaar semsg(_(e_readonlyvar), name); 558c785b9a7SBram Moolenaar return FAIL; 559c785b9a7SBram Moolenaar } 560*4cdb13ceSBram Moolenaar return check_typval_type(sv->sv_type, value); 56134db91f7SBram Moolenaar } 56234db91f7SBram Moolenaar } 56334db91f7SBram Moolenaar iemsg("check_script_var_type(): not found"); 564c785b9a7SBram Moolenaar return OK; // not really 56534db91f7SBram Moolenaar } 566c82a5b5dSBram Moolenaar 5678a7d6542SBram Moolenaar #endif // FEAT_EVAL 568