Version 1 of procstep

Updated 2015-11-08 14:28:52 by pooryorick

PYK 2015-11-08: procstep is s 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 [::list {now executing} $command]
   return $command
}

::tcl::proc errorhandler {cres copts}  {
   #puts $args
   ::puts [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]
}