@@ -4961,6 +4961,7 @@ typedef enum {
49614961 dest_vimvar ,
49624962 dest_script ,
49634963 dest_reg ,
4964+ dest_expr ,
49644965} assign_dest_T ;
49654966
49664967/*
@@ -5013,9 +5014,34 @@ generate_loadvar(
50135014 else
50145015 generate_LOAD (cctx , ISN_LOAD , lvar -> lv_idx , NULL , type );
50155016 break ;
5017+ case dest_expr :
5018+ // list or dict value should already be on the stack.
5019+ break ;
50165020 }
50175021}
50185022
5023+ /*
5024+ * Skip over "[expr]" or ".member".
5025+ * Does not check for any errors.
5026+ */
5027+ static char_u *
5028+ skip_index (char_u * start )
5029+ {
5030+ char_u * p = start ;
5031+
5032+ if (* p == '[' )
5033+ {
5034+ p = skipwhite (p + 1 );
5035+ (void )skip_expr (& p , NULL );
5036+ p = skipwhite (p );
5037+ if (* p == ']' )
5038+ return p + 1 ;
5039+ return p ;
5040+ }
5041+ // if (*p == '.')
5042+ return to_name_end (p + 1 , TRUE);
5043+ }
5044+
50195045 void
50205046vim9_declare_error (char_u * name )
50215047{
@@ -5069,6 +5095,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
50695095 int heredoc = FALSE;
50705096 type_T * type = & t_any ;
50715097 type_T * member_type = & t_any ;
5098+ type_T * rhs_type = & t_any ;
50725099 char_u * name = NULL ;
50735100 char_u * sp ;
50745101 int is_decl = cmdidx == CMD_let || cmdidx == CMD_var
@@ -5157,6 +5184,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
51575184 // TODO: check the length of a constant list here
51585185 generate_CHECKLEN (cctx , semicolon ? var_count - 1 : var_count ,
51595186 semicolon );
5187+ if (stacktype -> tt_member != NULL )
5188+ rhs_type = stacktype -> tt_member ;
51605189 }
51615190 }
51625191
@@ -5467,6 +5496,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
54675496 if (var_end > var_start + varlen )
54685497 {
54695498 // Something follows after the variable: "var[idx]" or "var.key".
5499+ // TODO: should we also handle "->func()" here?
54705500 if (is_decl )
54715501 {
54725502 emsg (_ (e_cannot_use_index_when_declaring_variable ));
@@ -5475,6 +5505,27 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
54755505
54765506 if (var_start [varlen ] == '[' || var_start [varlen ] == '.' )
54775507 {
5508+ char_u * after = var_start + varlen ;
5509+
5510+ // Only the last index is used below, if there are others
5511+ // before it generate code for the expression. Thus for
5512+ // "ll[1][2]" the expression is "ll[1]" and "[2]" is the index.
5513+ for (;;)
5514+ {
5515+ p = skip_index (after );
5516+ if (* p != '[' && * p != '.' )
5517+ break ;
5518+ after = p ;
5519+ }
5520+ if (after > var_start + varlen )
5521+ {
5522+ varlen = after - var_start ;
5523+ dest = dest_expr ;
5524+ // We don't know the type before evaluating the expression,
5525+ // use "any" until then.
5526+ type = & t_any ;
5527+ }
5528+
54785529 has_index = TRUE;
54795530 if (type -> tt_member == NULL )
54805531 member_type = & t_any ;
@@ -5511,7 +5562,6 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
55115562 }
55125563 else if (oplen > 0 )
55135564 {
5514- type_T * stacktype ;
55155565 int is_const = FALSE;
55165566
55175567 // For "var = expr" evaluate the expression.
@@ -5558,18 +5608,18 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
55585608 return FAIL ;
55595609 }
55605610
5561- stacktype = stack -> ga_len == 0 ? & t_void
5611+ rhs_type = stack -> ga_len == 0 ? & t_void
55625612 : ((type_T * * )stack -> ga_data )[stack -> ga_len - 1 ];
55635613 if (lvar != NULL && (is_decl || !has_type ))
55645614 {
5565- if ((stacktype -> tt_type == VAR_FUNC
5566- || stacktype -> tt_type == VAR_PARTIAL )
5615+ if ((rhs_type -> tt_type == VAR_FUNC
5616+ || rhs_type -> tt_type == VAR_PARTIAL )
55675617 && var_wrong_func_name (name , TRUE))
55685618 goto theend ;
55695619
55705620 if (new_local && !has_type )
55715621 {
5572- if (stacktype -> tt_type == VAR_VOID )
5622+ if (rhs_type -> tt_type == VAR_VOID )
55735623 {
55745624 emsg (_ (e_cannot_use_void_value ));
55755625 goto theend ;
@@ -5578,14 +5628,14 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
55785628 {
55795629 // An empty list or dict has a &t_unknown member,
55805630 // for a variable that implies &t_any.
5581- if (stacktype == & t_list_empty )
5631+ if (rhs_type == & t_list_empty )
55825632 lvar -> lv_type = & t_list_any ;
5583- else if (stacktype == & t_dict_empty )
5633+ else if (rhs_type == & t_dict_empty )
55845634 lvar -> lv_type = & t_dict_any ;
5585- else if (stacktype == & t_unknown )
5635+ else if (rhs_type == & t_unknown )
55865636 lvar -> lv_type = & t_any ;
55875637 else
5588- lvar -> lv_type = stacktype ;
5638+ lvar -> lv_type = rhs_type ;
55895639 }
55905640 }
55915641 else if (* op == '=' )
@@ -5595,17 +5645,17 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
55955645 // without operator check type here, otherwise below
55965646 if (has_index )
55975647 {
5598- use_type = use_type -> tt_member ;
5599- if (use_type == NULL )
5648+ use_type = member_type ;
5649+ if (member_type == NULL )
56005650 // could be indexing "any"
56015651 use_type = & t_any ;
56025652 }
5603- if (need_type (stacktype , use_type , -1 , cctx ,
5653+ if (need_type (rhs_type , use_type , -1 , cctx ,
56045654 FALSE, is_const ) == FAIL )
56055655 goto theend ;
56065656 }
56075657 }
5608- else if (* p != '=' && need_type (stacktype , member_type , -1 ,
5658+ else if (* p != '=' && need_type (rhs_type , member_type , -1 ,
56095659 cctx , FALSE, FALSE) == FAIL )
56105660 goto theend ;
56115661 }
@@ -5771,7 +5821,31 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
57715821 // - value
57725822 // - index
57735823 // - variable
5774- generate_loadvar (cctx , dest , name , lvar , type );
5824+ if (dest == dest_expr )
5825+ {
5826+ int c = var_start [varlen ];
5827+
5828+ // Evaluate "ll[expr]" of "ll[expr][idx]"
5829+ p = var_start ;
5830+ var_start [varlen ] = NUL ;
5831+ if (compile_expr0 (& p , cctx ) == OK && p != var_start + varlen )
5832+ {
5833+ // this should not happen
5834+ emsg (_ (e_missbrac ));
5835+ goto theend ;
5836+ }
5837+ var_start [varlen ] = c ;
5838+
5839+ type = stack -> ga_len == 0 ? & t_void
5840+ : ((type_T * * )stack -> ga_data )[stack -> ga_len - 1 ];
5841+ // now we can properly check the type
5842+ if (type -> tt_member != NULL
5843+ && need_type (rhs_type , type -> tt_member , -2 , cctx ,
5844+ FALSE, FALSE) == FAIL )
5845+ goto theend ;
5846+ }
5847+ else
5848+ generate_loadvar (cctx , dest , name , lvar , type );
57755849
57765850 if (type -> tt_type == VAR_LIST )
57775851 {
@@ -5785,7 +5859,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
57855859 }
57865860 else
57875861 {
5788- emsg (_ (e_listreq ));
5862+ emsg (_ (e_indexable_type_required ));
57895863 goto theend ;
57905864 }
57915865 }
@@ -5882,6 +5956,9 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
58825956 generate_STORE (cctx , ISN_STORE , lvar -> lv_idx , NULL );
58835957 }
58845958 break ;
5959+ case dest_expr :
5960+ // cannot happen
5961+ break ;
58855962 }
58865963 }
58875964
0 commit comments