def next_match(arr,idx)
      #fewer assertions in twin
      if @firstmatch
        result,@firstmatch=@firstmatch,nil
        assert result.first.empty? || ::Array===result.first.first
        #print "idx=#{idx}, inc=#{result.last}, arr.size=#{arr.size}\n"
#        assert idx+result.last<=arr.size
#        assert(progress.regsidx==result.first.size) 
        return result
      end
      
      @progress or return #not in twin ... ignore it
      
      assert progress.check_result

      i=@context.position_inc
=begin extents not used      
      extents= if i==0
        []
      else
        progress.position_stack[-i..-1]
      end
=end
            #this part's not in twin
      #'need to check for fewer matches here before rematching last matchset'
      
      #what if the match that gets discarded was returned by a matchset
      #that has more matches in it?
      #in that case, i is 1 and the body of this if should not be executed...      
      if @context.regsidx>@context.matcher.times.begin  #&& i>1
        progress.backup_stacks(@context) or raise
        huh #need to change progress.cursor.pos here too
        #result of backup_stacks is abandoned, leaked, orphaned
        #we don't want it anymore
        #but what if it's nil?
        
        #but now i need to undo all other progress state too, if 
        #the state was created with the match result just popped.
        #in general, it's not possible to distinguish state with the 
        #last match from state with the matches that might have preceeded it...
        #unless I create a backtracking point for each optional iteration
        #of the repeat matcher.
        #currently, making a backtracking point implies making a matchset
        #as well. I'll need a matchset the contains only 1 match.
        #ok, i think this is working now. no extra code needed here.
        
        @consumed-=pos-progress.position_stack.last
        #assert(@ri==Backtrace.clean_result(@ary).size)
        assert idx+@consumed<=arr.size
        assert progress.check_result
        result= [progress.clean_result, @consumed]
        assert progress.check_result
        return result
      end


        assert progress.check_result
      assert( (0..@progress.matcher.max_matches)===@progress.regsidx)
      result,di,ri=progress.last_next_match
      if result and @progress.matcher.enough_matches? ri #condition slightly different in twin
        result=[progress.clean_result,di]
        @consumed=di  #not in twin...why?
        #@progress.regsidx-=1
        assert ::Array===result.first.first
        assert idx+result.last<=arr.size
        assert progress.check_result
        #assert(@ri==result.first.size)
        return result
      end

      assert( (0..@progress.matcher.max_matches)===@progress.regsidx)
      #assert(@ri==Backtrace.clean_result(@ary).size)
      assert(progress.check_result)
      


      @progress.matchset_stack.empty? and return @progress=nil  #also checking @ary in twin... ignore it
        assert @progress.regsidx>0
        
      @progress.backtrack or return @progress=nil #@progress never set to nil like this in twin... ignore it

      #this is where the divergence widens. ri is a local in twin
 
        #assert(@ri==Backtrace.clean_result(@ary).size)
      assert(progress.check_result)
        mat,di,@ri=@progress.bt_match #mat is @ary in twin
        mat.nil? and return @progress=nil

        #assert(@ri==Backtrace.clean_result(mat).size)
        assert @progress.regsidx
      assert( (0..@progress.matcher.max_matches)===@progress.regsidx)

      result=[@progress.clean_result,di]
      @consumed=di  #no @consumed in twin
      assert ::Array===result.first.first
      assert idx+result.last<=arr.size
        assert progress.check_result
        #assert(@ri==result.last.size)
      return result
    end
def next_match(arr,idx)
      #fewer assertions in twin
      if @firstmatch
        result,@firstmatch=@firstmatch,nil
        assert result.first.empty? || ::Array===result.first.first
        #print "idx=#{idx}, inc=#{result.last}, arr.size=#{arr.size}\n"
#        assert idx+result.last<=arr.size
#        assert(progress.regsidx==result.first.size) 
        return result
      end
      
      @progress or return #not in twin ... ignore it
      
      assert progress.check_result

      i=@context.position_inc
=begin extents not used      
      extents= if i==0
        []
      else
        progress.position_stack[-i..-1]
      end
=end
            #this part's not in twin
      #'need to check for fewer matches here before rematching last matchset'
      
      #what if the match that gets discarded was returned by a matchset
      #that has more matches in it?
      #in that case, i is 1 and the body of this if should not be executed...      
      if @context.regsidx>@context.matcher.times.begin  #&& i>1
        progress.backup_stacks(@context) or raise
        huh #need to change progress.cursor.pos here too
        #result of backup_stacks is abandoned, leaked, orphaned
        #we don't want it anymore
        #but what if it's nil?
        
        #but now i need to undo all other progress state too, if 
        #the state was created with the match result just popped.
        #in general, it's not possible to distinguish state with the 
        #last match from state with the matches that might have preceeded it...
        #unless I create a backtracking point for each optional iteration
        #of the repeat matcher.
        #currently, making a backtracking point implies making a matchset
        #as well. I'll need a matchset the contains only 1 match.
        #ok, i think this is working now. no extra code needed here.
        
        @consumed-=pos-progress.position_stack.last
        #assert(@ri==Backtrace.clean_result(@ary).size)
        assert idx+@consumed<=arr.size
        assert progress.check_result
        result= [progress.clean_result, @consumed]
        assert progress.check_result
        return result
      end


        assert progress.check_result
      assert( (0..@progress.matcher.max_matches)===@progress.regsidx)
      result,di,ri=progress.last_next_match
      if result and @progress.matcher.enough_matches? ri #condition slightly different in twin
        result=[progress.clean_result,di]
        @consumed=di  #not in twin...why?
        #@progress.regsidx-=1
        assert ::Array===result.first.first
        assert idx+result.last<=arr.size
        assert progress.check_result
        #assert(@ri==result.first.size)
        return result
      end

      assert( (0..@progress.matcher.max_matches)===@progress.regsidx)
      #assert(@ri==Backtrace.clean_result(@ary).size)
      assert(progress.check_result)
      


      @progress.matchset_stack.empty? and return @progress=nil  #also checking @ary in twin... ignore it
        assert @progress.regsidx>0
        
      @progress.backtrack or return @progress=nil #@progress never set to nil like this in twin... ignore it

      #this is where the divergence widens. ri is a local in twin
 
        #assert(@ri==Backtrace.clean_result(@ary).size)
      assert(progress.check_result)
        mat,di,@ri=@progress.bt_match #mat is @ary in twin
        mat.nil? and return @progress=nil

        #assert(@ri==Backtrace.clean_result(mat).size)
        assert @progress.regsidx
      assert( (0..@progress.matcher.max_matches)===@progress.regsidx)

      result=[@progress.clean_result,di]
      @consumed=di  #no @consumed in twin
      assert ::Array===result.first.first
      assert idx+result.last<=arr.size
        assert progress.check_result
        #assert(@ri==result.last.size)
      return result
    end
very nearly identical to SubseqMatchSet#next_match