@@ -2741,36 +2741,76 @@ call_def_function(
27412741 // top of a for loop
27422742 case ISN_FOR :
27432743 {
2744- list_T * list = STACK_TV_BOT (-1 )-> vval . v_list ;
2744+ typval_T * ltv = STACK_TV_BOT (-1 );
27452745 typval_T * idxtv =
27462746 STACK_TV_VAR (iptr -> isn_arg .forloop .for_idx );
27472747
2748- // push the next item from the list
27492748 if (GA_GROW (& ectx .ec_stack , 1 ) == FAIL )
27502749 goto failed ;
2751- ++ idxtv -> vval .v_number ;
2752- if (list == NULL || idxtv -> vval .v_number >= list -> lv_len )
2750+ if (ltv -> v_type == VAR_LIST )
27532751 {
2754- // past the end of the list, jump to "endfor"
2755- ectx .ec_iidx = iptr -> isn_arg .forloop .for_end ;
2756- may_restore_cmdmod (& funclocal );
2752+ list_T * list = ltv -> vval .v_list ;
2753+
2754+ // push the next item from the list
2755+ ++ idxtv -> vval .v_number ;
2756+ if (list == NULL
2757+ || idxtv -> vval .v_number >= list -> lv_len )
2758+ {
2759+ // past the end of the list, jump to "endfor"
2760+ ectx .ec_iidx = iptr -> isn_arg .forloop .for_end ;
2761+ may_restore_cmdmod (& funclocal );
2762+ }
2763+ else if (list -> lv_first == & range_list_item )
2764+ {
2765+ // non-materialized range() list
2766+ tv = STACK_TV_BOT (0 );
2767+ tv -> v_type = VAR_NUMBER ;
2768+ tv -> v_lock = 0 ;
2769+ tv -> vval .v_number = list_find_nr (
2770+ list , idxtv -> vval .v_number , NULL );
2771+ ++ ectx .ec_stack .ga_len ;
2772+ }
2773+ else
2774+ {
2775+ listitem_T * li = list_find (list ,
2776+ idxtv -> vval .v_number );
2777+
2778+ copy_tv (& li -> li_tv , STACK_TV_BOT (0 ));
2779+ ++ ectx .ec_stack .ga_len ;
2780+ }
27572781 }
2758- else if (list -> lv_first == & range_list_item )
2782+ else if (ltv -> v_type == VAR_STRING )
27592783 {
2760- // non-materialized range() list
2761- tv = STACK_TV_BOT (0 );
2762- tv -> v_type = VAR_NUMBER ;
2763- tv -> v_lock = 0 ;
2764- tv -> vval .v_number = list_find_nr (
2765- list , idxtv -> vval .v_number , NULL );
2766- ++ ectx .ec_stack .ga_len ;
2784+ char_u * str = ltv -> vval .v_string ;
2785+ int len = str == NULL ? 0 : (int )STRLEN (str );
2786+
2787+ // Push the next character from the string. The index
2788+ // is for the last byte of the previous character.
2789+ ++ idxtv -> vval .v_number ;
2790+ if (idxtv -> vval .v_number >= len )
2791+ {
2792+ // past the end of the string, jump to "endfor"
2793+ ectx .ec_iidx = iptr -> isn_arg .forloop .for_end ;
2794+ may_restore_cmdmod (& funclocal );
2795+ }
2796+ else
2797+ {
2798+ int clen = mb_ptr2len (str + idxtv -> vval .v_number );
2799+
2800+ tv = STACK_TV_BOT (0 );
2801+ tv -> v_type = VAR_STRING ;
2802+ tv -> vval .v_string = vim_strnsave (
2803+ str + idxtv -> vval .v_number , clen );
2804+ ++ ectx .ec_stack .ga_len ;
2805+ idxtv -> vval .v_number += clen - 1 ;
2806+ }
27672807 }
27682808 else
27692809 {
2770- listitem_T * li = list_find ( list , idxtv -> vval . v_number );
2771-
2772- copy_tv ( & li -> li_tv , STACK_TV_BOT ( 0 ));
2773- ++ ectx . ec_stack . ga_len ;
2810+ // TODO: support Blob
2811+ semsg ( _ ( e_for_loop_on_str_not_supported ),
2812+ vartype_name ( ltv -> v_type ));
2813+ goto failed ;
27742814 }
27752815 }
27762816 break ;
0 commit comments