Version 0 of for in

Updated 2012-10-19 15:54:12 by pooryorick

This is a drop in replacement for the standard for command. It supports an expanded syntax for looping over [iterator protocol%|%iterators]

rename ::for for_core
interp alias {} ::for {} [namespace current]::for

proc for args {
    if {[lindex $args 1] eq "in"} {
        if {[llength $args] % 3 != 1} {
            return -code error "wrong number of arguments for [info level 0]"
        }
        set assigns {} 
        set assign_template {
            if {[namespace which $iter] eq {}} {
                variable $varname {}
            } else {
                variable $varname [$iter]
            }
        }

        set conditions {}
        set condition_template {[namespace which $iter] ne {}}
        while {[llength $args] > 1} {
            set args [lassign $args[unset args] varnames {} iter]
            foreach varname $varnames {
                lappend assigns [string map [list \$iter [list $iter] \$varname [list $varname]] \
                    $assign_template] 
            }
            lappend conditions [string map [list \$iter [list $iter]] $condition_template]
        }
        set assigns [join $assigns \n]
        set args [join $args \n]
        uplevel "while {[join $conditions { || }]} {$assigns\n$args}"
    } else {
        uplevel [list [namespace current]::for_core {*}$args]
    }
}