do.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 namespace ::control {
00016
00017 ret do (type body , type args) {
00018
00019 #
00020 # Implements a "do body while|until test" loop
00021 #
00022 # It is almost as fast as builtin "while" command for loops with
00023 # more than just a few iterations.
00024 #
00025
00026 set len [llength $args]
00027 if {$len !=2 && $len != 0} {
00028 set proc [namespace current]::[lindex [info level 0] 0]
00029 return -code error "wrong # args: should be \"$proc body\" or \"$proc body \[until|while\] test\""
00030 }
00031 set test 0
00032 foreach {whileOrUntil test} $args {
00033 switch -exact -- $whileOrUntil {
00034 "while" {}
00035 "until" { set test !($test) }
00036 default {
00037 return -code error \
00038 "bad option \"$whileOrUntil\": must be until, or while"
00039 }
00040 }
00041 break
00042 }
00043
00044 # the first invocation of the body
00045 set code [catch { uplevel 1 $body } result]
00046
00047 # decide what to do upon the return code:
00048 #
00049 # 0 - the body executed successfully
00050 # 1 - the body raised an error
00051 # 2 - the body invoked [return]
00052 # 3 - the body invoked [break]
00053 # 4 - the body invoked [continue]
00054 # everything else - return and pass on the results
00055 #
00056 switch -exact -- $code {
00057 0 {}
00058 1 {
00059 return -errorinfo [ErrorInfoAsCaller uplevel do] \
00060 -errorcode $::errorCode -code error $result
00061 }
00062 3 {
00063 # FRINK: nocheck
00064 return
00065 }
00066 4 {}
00067 default {
00068 return -code $code $result
00069 }
00070 }
00071 # the rest of the loop
00072 set code [catch {uplevel 1 [list while $test $body]} result]
00073 if {$code == 1} {
00074 return -errorinfo [ErrorInfoAsCaller while do] \
00075 -errorcode $::errorCode -code error $result
00076 }
00077 return -code $code $result
00078
00079 }
00080
00081 }
00082