[PYK] 2015-11-08: '''procstep''' is a drop-in replacement for `[proc]` that evaluates one command of a procedure body at at time, and a hook to inspect and manipulate the command before it is evaluated, and another to react to return conditions of the evaluation. ====== rename proc ::tcl::proc ::tcl::proc proc {name args body} { ::uplevel [::list ::tcl::proc $name $args [::list apply [::list args [ ::string map [::list {${body}} [::list $body]] { ::foreach command [::scriptSplit ${body}] { ::if {[::catch [::list ::uplevel 1 [ ::cmdhandler $command]] cres copts]} { ::tailcall ::errorhandler $cres $copts } } } ]] [uplevel {namespace current}]]] } ::tcl::proc cmdhandler command { ::puts stderr [::list {now executing} $command] return $command } ::tcl::proc errorhandler {cres copts} { ::puts stderr [list {got an error} $cres] #puts [uplevel info locals] } ====== Here is variant that improves runtime performance quite a bit by rewriting the body when the procedure is created. This leaves no place to put the result variables of the `[catch]`, so they get stuffed into `::tcl` namespace instead: ====== ::tcl::proc proc {name args body} { set newbody {} ::foreach command [::scriptSplit $body] { ::append newbody [::string map [::list {${command}} [::list $command]] { ::if {[::catch {if 1 [ ::cmdhandler ${command}]} ::tcl::cres ::tcl::copts]} { ::errorhandler $::tcl::cres $::tcl::copts } }] } ::uplevel [::list ::tcl::proc $name $args $newbody] } ====== <> debugging | macro