@@ -3201,6 +3201,7 @@ set_var_const(
32013201 typval_T * tv = tv_arg ;
32023202 typval_T bool_tv ;
32033203 dictitem_T * di ;
3204+ typval_T * dest_tv = NULL ;
32043205 char_u * varname ;
32053206 hashtab_T * ht ;
32063207 int is_script_local ;
@@ -3241,182 +3242,210 @@ set_var_const(
32413242
32423243 di = find_var_in_ht (ht , 0 , varname , TRUE);
32433244
3244- // Search in parent scope which is possible to reference from lambda
3245- if (di == NULL )
3246- di = find_var_in_scoped_ht (name , TRUE);
3247-
3248- if ((tv -> v_type == VAR_FUNC || tv -> v_type == VAR_PARTIAL )
3249- && var_wrong_func_name (name , di == NULL ))
3250- goto failed ;
3251-
3252- if (need_convert_to_bool (type , tv ))
3245+ if (di == NULL && var_in_vim9script )
32533246 {
3254- // Destination is a bool and the value is not, but it can be converted.
3255- CLEAR_FIELD (bool_tv );
3256- bool_tv .v_type = VAR_BOOL ;
3257- bool_tv .vval .v_number = tv2bool (tv ) ? VVAL_TRUE : VVAL_FALSE ;
3258- tv = & bool_tv ;
3259- }
3247+ imported_T * import = find_imported (varname , 0 , NULL );
32603248
3261- if (di != NULL )
3262- {
3263- // Item already exists. Allowed to replace when reloading.
3264- if ((di -> di_flags & DI_FLAGS_RELOAD ) == 0 )
3249+ if (import != NULL )
32653250 {
3266- if ((flags & (ASSIGN_CONST | ASSIGN_FINAL ))
3267- && (flags & ASSIGN_FOR_LOOP ) == 0 )
3268- {
3269- emsg (_ (e_cannot_mod ));
3270- goto failed ;
3271- }
3251+ scriptitem_T * si = SCRIPT_ITEM (import -> imp_sid );
3252+ svar_T * sv ;
32723253
3273- if ( is_script_local && vim9script
3274- && ( flags & ( ASSIGN_NO_DECL | ASSIGN_DECL ) ) == 0 )
3254+ // imported variable from another script
3255+ if (( flags & ASSIGN_NO_DECL ) == 0 )
32753256 {
3276- semsg (_ (e_redefining_script_item_str ), name );
3257+ semsg (_ (e_redefining_imported_item_str ), name );
32773258 goto failed ;
32783259 }
3260+ sv = ((svar_T * )si -> sn_var_vals .ga_data )
3261+ + import -> imp_var_vals_idx ;
3262+ // TODO: check the type
3263+ // TODO: check for const and locked
3264+ dest_tv = sv -> sv_tv ;
3265+ }
3266+ }
32793267
3280- if (var_in_vim9script )
3281- {
3282- where_T where ;
3268+ if (dest_tv == NULL )
3269+ {
3270+ // Search in parent scope which is possible to reference from lambda
3271+ if (di == NULL )
3272+ di = find_var_in_scoped_ht (name , TRUE);
32833273
3284- // check the type and adjust to bool if needed
3285- where .wt_index = var_idx ;
3286- where .wt_variable = TRUE;
3287- if (check_script_var_type (& di -> di_tv , tv , name , where ) == FAIL )
3288- goto failed ;
3289- }
3274+ if ((tv -> v_type == VAR_FUNC || tv -> v_type == VAR_PARTIAL )
3275+ && var_wrong_func_name (name , di == NULL ))
3276+ goto failed ;
32903277
3291- if (var_check_permission (di , name ) == FAIL )
3292- goto failed ;
3293- }
3294- else
3278+ if (need_convert_to_bool (type , tv ))
32953279 {
3296- // can only redefine once
3297- di -> di_flags &= ~DI_FLAGS_RELOAD ;
3298-
3299- // A Vim9 script-local variable is also present in sn_all_vars and
3300- // sn_var_vals. It may set "type" from "tv".
3301- if (var_in_vim9script )
3302- update_vim9_script_var (FALSE, di , flags , tv , & type ,
3303- (flags & ASSIGN_NO_MEMBER_TYPE ) == 0 );
3280+ // Destination is a bool and the value is not, but it can be converted.
3281+ CLEAR_FIELD (bool_tv );
3282+ bool_tv .v_type = VAR_BOOL ;
3283+ bool_tv .vval .v_number = tv2bool (tv ) ? VVAL_TRUE : VVAL_FALSE ;
3284+ tv = & bool_tv ;
33043285 }
33053286
3306- // existing variable, need to clear the value
3307-
3308- // Handle setting internal di: variables separately where needed to
3309- // prevent changing the type.
3310- if (ht == & vimvarht )
3287+ if (di != NULL )
33113288 {
3312- if (di -> di_tv .v_type == VAR_STRING )
3289+ // Item already exists. Allowed to replace when reloading.
3290+ if ((di -> di_flags & DI_FLAGS_RELOAD ) == 0 )
33133291 {
3314- VIM_CLEAR ( di -> di_tv . vval . v_string );
3315- if ( copy || tv -> v_type != VAR_STRING )
3292+ if (( flags & ( ASSIGN_CONST | ASSIGN_FINAL ))
3293+ && ( flags & ASSIGN_FOR_LOOP ) == 0 )
33163294 {
3317- char_u * val = tv_get_string (tv );
3295+ emsg (_ (e_cannot_mod ));
3296+ goto failed ;
3297+ }
33183298
3319- // Careful: when assigning to v:errmsg and tv_get_string()
3320- // causes an error message the variable will already be set.
3321- if (di -> di_tv .vval .v_string == NULL )
3322- di -> di_tv .vval .v_string = vim_strsave (val );
3299+ if (is_script_local && vim9script
3300+ && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL )) == 0 )
3301+ {
3302+ semsg (_ (e_redefining_script_item_str ), name );
3303+ goto failed ;
33233304 }
3324- else
3305+
3306+ if (var_in_vim9script )
33253307 {
3326- // Take over the string to avoid an extra alloc/free.
3327- di -> di_tv .vval .v_string = tv -> vval .v_string ;
3328- tv -> vval .v_string = NULL ;
3308+ where_T where ;
3309+
3310+ // check the type and adjust to bool if needed
3311+ where .wt_index = var_idx ;
3312+ where .wt_variable = TRUE;
3313+ if (check_script_var_type (& di -> di_tv , tv , name , where ) == FAIL )
3314+ goto failed ;
33293315 }
3330- goto failed ;
3316+
3317+ if (var_check_permission (di , name ) == FAIL )
3318+ goto failed ;
33313319 }
3332- else if ( di -> di_tv . v_type == VAR_NUMBER )
3320+ else
33333321 {
3334- di -> di_tv .vval .v_number = tv_get_number (tv );
3335- if (STRCMP (varname , "searchforward" ) == 0 )
3336- set_search_direction (di -> di_tv .vval .v_number ? '/' : '?' );
3337- #ifdef FEAT_SEARCH_EXTRA
3338- else if (STRCMP (varname , "hlsearch ") == 0 )
3322+ // can only redefine once
3323+ di -> di_flags &= ~DI_FLAGS_RELOAD ;
3324+
3325+ // A Vim9 script-local variable is also present in sn_all_vars and
3326+ // sn_var_vals. It may set "type" from "tv".
3327+ if (var_in_vim9script )
3328+ update_vim9_script_var (FALSE, di , flags , tv , & type ,
3329+ (flags & ASSIGN_NO_MEMBER_TYPE ) == 0 );
3330+ }
3331+
3332+ // existing variable, need to clear the value
3333+
3334+ // Handle setting internal di: variables separately where needed to
3335+ // prevent changing the type.
3336+ if (ht == & vimvarht )
3337+ {
3338+ if (di -> di_tv .v_type == VAR_STRING )
33393339 {
3340- no_hlsearch = !di -> di_tv .vval .v_number ;
3341- redraw_all_later (SOME_VALID );
3340+ VIM_CLEAR (di -> di_tv .vval .v_string );
3341+ if (copy || tv -> v_type != VAR_STRING )
3342+ {
3343+ char_u * val = tv_get_string (tv );
3344+
3345+ // Careful: when assigning to v:errmsg and tv_get_string()
3346+ // causes an error message the variable will already be set.
3347+ if (di -> di_tv .vval .v_string == NULL )
3348+ di -> di_tv .vval .v_string = vim_strsave (val );
3349+ }
3350+ else
3351+ {
3352+ // Take over the string to avoid an extra alloc/free.
3353+ di -> di_tv .vval .v_string = tv -> vval .v_string ;
3354+ tv -> vval .v_string = NULL ;
3355+ }
3356+ goto failed ;
33423357 }
3358+ else if (di -> di_tv .v_type == VAR_NUMBER )
3359+ {
3360+ di -> di_tv .vval .v_number = tv_get_number (tv );
3361+ if (STRCMP (varname , "searchforward" ) == 0 )
3362+ set_search_direction (di -> di_tv .vval .v_number ? '/' : '?' );
3363+ #ifdef FEAT_SEARCH_EXTRA
3364+ else if (STRCMP (varname , "hlsearch ") == 0 )
3365+ {
3366+ no_hlsearch = !di -> di_tv .vval .v_number ;
3367+ redraw_all_later (SOME_VALID );
3368+ }
33433369#endif
3344- goto failed ;
3370+ goto failed ;
3371+ }
3372+ else if (di -> di_tv .v_type != tv -> v_type )
3373+ {
3374+ semsg (_ ("E963: setting %s to value with wrong type" ), name );
3375+ goto failed ;
3376+ }
33453377 }
3346- else if (di -> di_tv .v_type != tv -> v_type )
3378+
3379+ clear_tv (& di -> di_tv );
3380+ }
3381+ else
3382+ {
3383+ // Item not found, check if a function already exists.
3384+ if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL )) == 0
3385+ && lookup_scriptitem (name , STRLEN (name ), FALSE, NULL ) == OK )
33473386 {
3348- semsg (_ ("E963: setting %s to value with wrong type" ), name );
3387+ semsg (_ (e_redefining_script_item_str ), name );
33493388 goto failed ;
33503389 }
3351- }
33523390
3353- clear_tv (& di -> di_tv );
3354- }
3355- else
3356- {
3357- // Item not found, check if a function already exists.
3358- if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL )) == 0
3359- && lookup_scriptitem (name , STRLEN (name ), FALSE, NULL ) == OK )
3360- {
3361- semsg (_ (e_redefining_script_item_str ), name );
3362- goto failed ;
3363- }
3391+ // add a new variable
3392+ if (var_in_vim9script && (flags & ASSIGN_NO_DECL ))
3393+ {
3394+ semsg (_ (e_unknown_variable_str ), name );
3395+ goto failed ;
3396+ }
33643397
3365- // add a new variable
3366- if (var_in_vim9script && ( flags & ASSIGN_NO_DECL ))
3367- {
3368- semsg (_ (e_unknown_variable_str ), name );
3369- goto failed ;
3370- }
3398+ // Can't add "v:" or "a:" variable.
3399+ if (ht == & vimvarht || ht == get_funccal_args_ht ( ))
3400+ {
3401+ semsg (_ (e_illvar ), name );
3402+ goto failed ;
3403+ }
33713404
3372- // Can't add "v:" or "a:" variable.
3373- if (ht == & vimvarht || ht == get_funccal_args_ht ())
3374- {
3375- semsg (_ (e_illvar ), name );
3376- goto failed ;
3377- }
3405+ // Make sure the variable name is valid. In Vim9 script an autoload
3406+ // variable must be prefixed with "g:".
3407+ if (!valid_varname (varname , !vim9script
3408+ || STRNCMP (name , "g:" , 2 ) == 0 ))
3409+ goto failed ;
33783410
3379- // Make sure the variable name is valid. In Vim9 script an autoload
3380- // variable must be prefixed with "g:".
3381- if (!valid_varname (varname , !vim9script
3382- || STRNCMP (name , "g:" , 2 ) == 0 ))
3383- goto failed ;
3411+ di = alloc (sizeof (dictitem_T ) + STRLEN (varname ));
3412+ if (di == NULL )
3413+ goto failed ;
3414+ STRCPY (di -> di_key , varname );
3415+ if (hash_add (ht , DI2HIKEY (di )) == FAIL )
3416+ {
3417+ vim_free (di );
3418+ goto failed ;
3419+ }
3420+ di -> di_flags = DI_FLAGS_ALLOC ;
3421+ if (flags & (ASSIGN_CONST | ASSIGN_FINAL ))
3422+ di -> di_flags |= DI_FLAGS_LOCK ;
33843423
3385- di = alloc (sizeof (dictitem_T ) + STRLEN (varname ));
3386- if (di == NULL )
3387- goto failed ;
3388- STRCPY (di -> di_key , varname );
3389- if (hash_add (ht , DI2HIKEY (di )) == FAIL )
3390- {
3391- vim_free (di );
3392- goto failed ;
3424+ // A Vim9 script-local variable is also added to sn_all_vars and
3425+ // sn_var_vals. It may set "type" from "tv".
3426+ if (var_in_vim9script )
3427+ update_vim9_script_var (TRUE, di , flags , tv , & type ,
3428+ (flags & ASSIGN_NO_MEMBER_TYPE ) == 0 );
33933429 }
3394- di -> di_flags = DI_FLAGS_ALLOC ;
3395- if (flags & (ASSIGN_CONST | ASSIGN_FINAL ))
3396- di -> di_flags |= DI_FLAGS_LOCK ;
3397-
3398- // A Vim9 script-local variable is also added to sn_all_vars and
3399- // sn_var_vals. It may set "type" from "tv".
3400- if (var_in_vim9script )
3401- update_vim9_script_var (TRUE, di , flags , tv , & type ,
3402- (flags & ASSIGN_NO_MEMBER_TYPE ) == 0 );
3430+
3431+ dest_tv = & di -> di_tv ;
34033432 }
34043433
34053434 if (copy || tv -> v_type == VAR_NUMBER || tv -> v_type == VAR_FLOAT )
3406- copy_tv (tv , & di -> di_tv );
3435+ copy_tv (tv , dest_tv );
34073436 else
34083437 {
3409- di -> di_tv = * tv ;
3410- di -> di_tv . v_lock = 0 ;
3438+ * dest_tv = * tv ;
3439+ dest_tv -> v_lock = 0 ;
34113440 init_tv (tv );
34123441 }
34133442
34143443 if (vim9script && type != NULL )
34153444 {
3416- if (type -> tt_type == VAR_DICT && di -> di_tv . vval .v_dict != NULL )
3417- di -> di_tv . vval .v_dict -> dv_type = alloc_type (type );
3418- else if (type -> tt_type == VAR_LIST && di -> di_tv . vval .v_list != NULL )
3419- di -> di_tv . vval .v_list -> lv_type = alloc_type (type );
3445+ if (type -> tt_type == VAR_DICT && dest_tv -> vval .v_dict != NULL )
3446+ dest_tv -> vval .v_dict -> dv_type = alloc_type (type );
3447+ else if (type -> tt_type == VAR_LIST && dest_tv -> vval .v_list != NULL )
3448+ dest_tv -> vval .v_list -> lv_type = alloc_type (type );
34203449 }
34213450
34223451 // ":const var = value" locks the value
@@ -3425,8 +3454,9 @@ set_var_const(
34253454 // Like :lockvar! name: lock the value and what it contains, but only
34263455 // if the reference count is up to one. That locks only literal
34273456 // values.
3428- item_lock (& di -> di_tv , DICT_MAXNEST , TRUE, TRUE);
3457+ item_lock (dest_tv , DICT_MAXNEST , TRUE, TRUE);
34293458 return ;
3459+
34303460failed :
34313461 if (!copy )
34323462 clear_tv (tv_arg );
0 commit comments