do.tcl

Go to the documentation of this file.
00001 /*  do.tcl --*/
00002 /* */
00003 /*         Tcl implementation of a "do ... while|until" loop.*/
00004 /* */
00005 /*  Originally written for the "Texas Tcl Shootout" programming contest*/
00006 /*  at the 2000 Tcl Conference in Austin/Texas.*/
00007 /* */
00008 /*  Copyright (c) 2001 by Reinhard Max <Reinhard.Max@gmx.de>*/
00009 /* */
00010 /*  See the file "license.terms" for information on usage and redistribution*/
00011 /*  of this file, and for a DISCLAIMER OF ALL WARRANTIES.*/
00012 /* */
00013 /*  RCS: @(#) $Id: do.tcl,v 1.6 2004/01/15 06:36:12 andreas_kupries Exp $*/
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 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1