[Richard Suchenwirth] 2013-12-01 - Last night on the Tclers' chat, [stu] challenged me to write a visual emulator for [TAL]. Challenge accepted, after some 3 hours here is the initial code that managed to step through the TAL code emulating [hypot]: [tal.tcl_002.png] Of the 130 TAL instructions, only 6 have been implemented so far, just the bare minimum to get the [hypot] example going... But more is to come. ====== #!/usr/bin/env tclkit # vtal.tcl -- Visual TAL set thisdir [file dirname [info script]] source $thisdir/tal.tcl proc vtal {{w ""}} { global g set g(stack) {} package require Tk if {$w ne ""} {pack [frame $w] -fill both -expand 1} pack [label $w.info -textvariable Info] -side bottom set ::Info "Welcome to Visual TAL" pack [frame $w.right] -side right pack [label $w.right.1 -text "Local variables"] set g(vars) $w.right.vars pack [frame $g(vars)] pack [label $w.right.2 -text Stack] pack [text $w.right.stack -width 40] set g(stk) $w.right.stack pack [scrollbar $w.y -command "$w.t yscroll"] -side right -fill y pack [text $w.t -wrap word \ -width 80 -yscrollcommand "$w.y set"] -fill both -expand 1 $w.t tag configure hilite -background yellow set g(txt) $w.t foreach i {red blue} {$w.t tag configure $i -foreground $i} bind $w.t <1> {vtal.hilite %W .} bind all {vtal.step $g(txt)} } proc vtal.show {w str} { $w delete 1.0 end foreach line [split $str \n] { if {[regexp {^(proc|\})} $line]} { $w insert end $line\n blue } else { foreach {code cmt} [split $line #] break $w insert end $code "" #$cmt\n red } } $w tag add hilite 2.0 2.end vtal.vars } proc vtal.vars {} { global g slot set w $g(vars) eval destroy [winfo children $w] set i 0 foreach {num lvar} [array get slot] { set varname [lindex $lvar end] grid [label $w.[incr i] -text $lvar] \ [entry $w.[incr i] -textvariable g(var,$varname)] } } proc vtal.step w { foreach {from to} [$w tag ranges hilite] break set line [lindex [split $from .] 0] set cmd [$w get $from $to] set ::Info $cmd incr line set line [vtal.run $cmd $line] vtal.hilite $w $line } proc vtal.run {cmd line} { foreach part [split $cmd ";"] { switch [lindex $part 0] { add {push [expr {[pop]+[pop]}]} expon {set x [pop]; push [expr {[pop]**$x}]} invokeStk {push [vtal.invoke [lindex $part 1]]} load {push [vtal.load [lindex $part 1]]} pop pop push {push [lindex $part 1]} default {set ::info "$part not yet implemented"} } } return $line } proc vtal.invoke num { global g set cmd {} while {$num > 0} { set cmd [linsert $cmd 0 [pop]] incr num -1 } catch $cmd res return $res } proc vtal.load name { global g return $g(var,$name) } proc pop {} { global g set res [lindex $g(stack) 0] set g(stack) [lrange $g(stack) 1 end] vtal.showstack return $res } proc push what { global g set g(stack) [linsert $g(stack) 0 $what] vtal.showstack } proc vtal.showstack {} { global g $g(stk) delete 1.0 end $g(stk) insert 1.0 [join $g(stack) \n] } proc vtal.hilite {w {line .}} { if {$line eq "."} {set line [lindex [split [$w index insert] .] 0]} $w tag remove hilite 1.0 end $w tag add hilite $line.0 $line.end } vtal if [catch {set asm [aproc f {x y} {expr {sqrt($x**2 + $y**2)}} -x]} { set asm {proc f {x y} {asm { push tcl::mathfunc::sqrt ;# (0) push1 0 # "tcl::mathfunc::sqrt" load x ;# (2) loadScalar1 %v0 # var "x" push 2 ;# (4) push1 1 # "2" expon ;# (6) expon load y ;# (7) loadScalar1 %v1 # var "y" push 2 ;# (9) push1 1 # "2" expon ;# (11) expon add ;# (12) add invokeStk 2 ;# (13) invokeStk1 2 tryCvtToNumeric ;# (15) tryCvtToNumeric ;# (16) done }} } vtal.show .t $asm ====== <>Enter Category Here