1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Single-line DO inside nested multi-line DOs?

Discussion in 'Support' started by vefatica, Oct 11, 2012.

  1. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,972
    Likes Received:
    30
    The BTM below is contrived to be fast and make a point. It's outer 2 nested DO loops make it count from from 1 to 4. If it's inner (nonsense) DO loop is replaced by a single-line DO, the BTM only counts to 2 (terminating when the outermost DO loop should iterate).

    Code:
    setlocal
    set count=0
    do q=1 to 2
    do r=1 to 2
    
    ::do i=1 to 2 ( set a=a )
    do i=1 to 2
        set a=a
    enddo
    
    set /a count+=1
    echo %count
    
    enddo
    enddo
    quit
     
  2. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,520
    Likes Received:
    4
    TCC 14.02.40 Windows XP [Version 5.1.2600]

    I tested a the variant below, which differs from the inline version of the original by adding more ECHO statements to monitor progress, and using a progress monitoring ECHO in the inline DO instead of the "nonsense statement set a=a".
    Code:
       1 : @echo off
       2 : setlocal
       3 : set count=0
       4 : echo line %_batchline
       5 : do q=1 to 2
       6 : echo line %_batchline
       7 :   do r=1 to 2
       8 :     echo line %_batchline
       9 :       do i=1 to 2 ( echo line %_batchline count=%count q=%q r=%r i=%i )
      10 :     set /a count+=1
      11 :     echo line %_batchline count=%count q=%q r=%r
      12 :   enddo
      13 :   echo line %_batchline count=%count q=%q
      14 : enddo
      15 : echo line %_batchline
      16 : quit
    

    This is the redirected output:
    line 4
    line 6
    line 8
    line 9 count=0 q=1 r=1 i=1
    line 9 count=0 q=1 r=1 i=2
    line 11 count=1 q=1 r=1
    line 8
    line 9 count=1 q=1 r=2 i=1
    line 9 count=1 q=1 r=2 i=2
    line 11 count=2 q=1 r=2
    line 15



    I then replaced the inline DO with a normal DO:
    Code:
       1 : @echo off
       2 : setlocal
       3 : set count=0
       4 : echo line %_batchline
       5 : do q=1 to 2
       6 : echo line %_batchline
       7 :   do r=1 to 2
       8 :     echo line %_batchline
       9 :       do i=1 to 2 
      10 :         echo line %_batchline count=%count q=%q r=%r i=%i
      11 :       enddo
      12 :     set /a count+=1
      13 :     echo line %_batchline count=%count q=%q r=%r
      14 :   enddo
      15 :   echo line %_batchline count=%count q=%q
      16 : enddo
      17 : echo line %_batchline
      18 : quit
    

    This is the output of the second version:

    line 4
    line 6
    line 8
    line 10 count=0 q=1 r=1 i=1
    line 10 count=0 q=1 r=1 i=2
    line 13 count=1 q=1 r=1
    line 8
    line 10 count=1 q=1 r=2 i=1
    line 10 count=1 q=1 r=2 i=2
    line 13 count=2 q=1 r=2
    line 15 count=2 q=1
    line 6
    line 8
    line 10 count=2 q=2 r=1 i=1
    line 10 count=2 q=2 r=1 i=2
    line 13 count=3 q=2 r=1
    line 8
    line 10 count=3 q=2 r=2 i=1
    line 10 count=3 q=2 r=2 i=2
    line 13 count=4 q=2 r=2
    line 15 count=4 q=2
    line 17


    Comparison of the two outputs shows that the inline DO somehow interferes with the outermost loop, and causes it to terminate after the first iteration. I also changed all loop upper limits from 2 to 3, and once again the outermost (DO q) loop terminated short. I also determined that ensuring whitespace between the loop control variable name and the equal sign = and between the sign and the start value has no effect.

    Rex, I suggest the documentation of the single line DO should have a subtitle, and the grouping parentheses be referred to as "left parenthesis (" etc. for clarity. Not all screens display the boldness of ( distinctively.
     
  3. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,870
    Likes Received:
    83
    I will change the help to make it clearer that single-line DO's are not supported in batch files, and that they cannot be nested. (I would have banned them entirely in batch files, but I was worried about people defining them in aliases and then referencing the alias in a batch file.)
     
  4. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,520
    Likes Received:
    4
  5. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,870
    Likes Received:
    83
    A brief test showed that the problem isn't with the single-line do nested in non-single-line DO's, but with the (unnecessary) QUIT combined with the single-line DO nested in multiple non-single-line DO's.

    Since this isn't a supported use, and it provides no benefit (and several drawbacks), and since the workaround is to use the documented format, I'm inclined to think it's not worth tearing the parser apart (and breaking other things) to try to support it.
     
  6. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,972
    Likes Received:
    30
    It may not be worth tearing the parser apart but it does provide the benefit of speed, especially when doing small things many, many times.
    Code:
    v:\> type docompare.btm
    timer
    do i=1 to 100000 ( set a=0 )
    timer
     
    timer
    do i=1 to 100000
            set a=0
    enddo
    timer
     
    v:\> docompare.btm
    Timer 1 on: 10:53:58
    Timer 1 off: 10:54:08  Elapsed: 0:00:09.80
    Timer 1 on: 10:54:08
    Timer 1 off: 10:54:25  Elapsed: 0:00:16.83
     
  7. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,972
    Likes Received:
    30
    In a simple test outside a batch file, nesting seems OK.

    Code:
    v:\> do i=0 to 1 ( do j=0 to 1 ( do k=0 to 1 ( echo %i %j %k ) ) )
    0 0 0
    0 0 1
    0 1 0
    0 1 1
    1 0 0
    1 0 1
    1 1 0
    1 1 1
     
  8. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,520
    Likes Received:
    4
    I don't understand how a QUIT command, which is past the outermost ENDDO Replacing QUIT with EXIT (which may be necessary) in the last line the output was identical.

    I tried another version, no QUIT command, no aliases, one more loop, updating COUNT inside single line DO :
    Code:
       1 : @echo off
       2 : setlocal
       3 : unalias *
       4 : unset *
       5 : set count=0
       6 : echo line %_batchline count=%count
       7 : do q = 1 to 3
       8 : echo line %_batchline
       9 :   do r = 1 to 3
      10 :     echo line %_batchline
      11 :     do s = 1 to 3
      12 :       echo line %_batchline
      13 :         do i = 1 to 3 ( set /a count+=1 %+ echo line %_batchline count=%count q=%q r=%r s=%s i=%i )
      14 :       echo line %_batchline count=%count q=%q r=%r s=%s
      15 :     enddo
      16 :     echo line %_batchline count=%count q=%q r=%r
      17 :   enddo
      18 :   echo line %_batchline count=%count q=%q
      19 : enddo
      20 : echo line %_batchline count=%count
    
    Surprise!!! the ECHO in line 16 is never reported! But line 20 reported 3 times... Seems that using a single-line DO in a batch file mixes up the parser, it executes a command outside of an enclosing DO instead of inside.

    It seems to me that the single line DO confuses the part of the parser which keeps track of loop ends of the already parsed batch file, possibly by searching for ENDDO. As fas as I am concerned, prohibiting "single line DO" in batch files, and reporting them as errors if used is OK.
     
  9. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    9,870
    Likes Received:
    83
    Not really; running your test here shows:

    Code:
    Timer 1 on: 12:23:00
    Timer 1 off: 12:23:05  Elapsed: 0:00:04.57
    Timer 1 on: 12:23:05
    Timer 1 off: 12:23:12  Elapsed: 0:00:06.20
    
    The parser changes necessary would eat up most of that difference (and also make *all* DO's significantly slower). Plus the inability to debug single-line DO's means the time you spend trying to debug anything other than the most trivial DO will probably be several orders of magnitude greater than the time savings in running the batch file for the rest of your life.
     
  10. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,520
    Likes Received:
    4
    Build 41 apparently solved this issue. In my tests the single-line DO and the ENDDO versions generated identical reports.
     

Share This Page