Search code examples
vbatclnested-loopsbreak

Simulate the "exit do" statement fused in vba in tcl


This question is related to Breaking parent loop in tcl , but I am not able to implement the answer to my current code.

I have a proc written in VBA for Excel which uses "Exit do":

Do While i < numofentries
    Debug.Print "------------------"
    Debug.Print "j = " & j
    Debug.Print "length | Element i"
    path_beg = i
    path_end = i
    Length = 0
    length_l = 0
    length_u = 0
    blnAngle = True
    Do While Length < minlength
        If (angles(i) < limitangle Or path_beg = i) Then
            Length = Length + ElemEdgeLengths(i)
            Debug.Print Length & " | " & i
            path_end = i
            i = i + 1
            If i = numofentries Then Exit Do
        Else
            Debug.Print "Angle change..."
            If path_end = path_beg Then
                path(j - 1) = path_end
                blnAngle = False
                Debug.Print "1 Elm only: included to predecessor path:"
                Debug.Print "path_end of path j = " & j - 1 & " changed to " & path_end
            Else
                path(j) = path_end
                j = j + 1
                blnAngle = False
                Debug.Print path_end - path_beg + 1 & " Elms: own path with length " & Length
            End If
            Exit Do
        End If
    Loop
    If blnAngle = True Then
        length_l = Abs(Length - ElemEdgeLengths(path_end - 1) - minlength)
        length_u = Abs(Length - minlength)
        If length_l <= length_u Then
            i = path_end
            path(j) = path_end - 1
            j = j + 1
            Debug.Print "last Elm set to " & path_end - 1
        Else
            path(j) = path_end
            j = j + 1
            Debug.Print "last Elm is " & path_end
        End If
    End If
Loop

I have "translated" the sub to tcl like this, but I am not able to simulate the behaviour of ExitDo correctly. How can I recode the VBA Sub in Tcl correctly ? :


proc magictrap {code body} {
    if {$code <= 4} {error "bad magic code"}; # Lower values reserved for Tcl
    if {[catch {uplevel 1 $body} msg opt] == $code} return
    return -options $opt $msg
}
proc magicthrow code {return -code $code "doesn't matter what this is"}



proc pathfinder {ElemEdgeLengths minlength LimitAngle angles} {
set j 0
set i 0
set numofentries [llength $ElemEdgeLengths]        

    while { $i < $numofentries }  {    

        set path_beg $i
        set path_end $i
        set length 0        
        set length_l 0
        set length_u 0
        set blnAngle 1

        while { ( $length < $minlength )  } { 

            if { ( [lindex $angles $i] < $LimitAngle ) || ( $path_beg == $i ) } {            
                set length [ expr { $length + [lindex $ElemEdgeLengths $i] } ]
                set path_end $i
                incr i 
                if { $i == $numofentries } { magicthrow 5 }
            } else {
                if { $path_end == $path_beg } {                     
                    set k [expr { $j - 1 }]
                    set path($k) $path_end
                    set blnAngle 0                    
                } else {
                    set path($j) $path_end
                    incr j 
                    set blnAngle 0
                } 
                set length inf
            }                        
        }

        if { $blnAngle == 1  } {
            set length_l [ expr { abs( $length - [lindex $ElemEdgeLengths [expr {$path_end - 1} ] ] - $minlength   ) } ]
            set length_u [ expr { abs( $length - $minlength ) } ]    
        }

        if { $length_l <= $length_u } {
            set i $path_end
            set path($j) [expr {$path_end - 1}]
            incr j                         
        } else {
            set path($j) $path_end
            incr j
        }

    }

    return  $path

}

Solution

  • "break" exits the innermost loop.

    you could set a boolean variable at the "exit do" location:

        set blnBreak 1
        break
    

    just outside the loop you will have to test it:

        if { $blnBreak == 1  } {
            break
        }