Posted to tcl by dbohdan at Fri Jan 27 22:50:24 GMT 2017view pretty
package require Tcl 8.6 namespace eval bf {} namespace eval bf::tape { variable data variable pos proc current {} { variable data variable pos return [lindex $data $pos] } proc inc x { variable data variable pos lset data $pos [expr {[current] + $x}] } proc move x { variable data variable pos incr pos $x while {$pos >= [llength $data]} { lappend data 0 } } } namespace eval bf { proc parse source { set res {} while 1 { set c [lindex $source 0] if {$c eq {}} break set source [lrange $source 1 end] switch -exact -- $c { + { lappend res [list INC 1] } - { lappend res [list INC -1] } > { lappend res [list MOVE 1] } < { lappend res [list MOVE -1] } . { lappend res [list PRINT {}] } \[ { lassign [parse $source] loop_code source lappend res [list LOOP $loop_code] } \] { break } default {} } } return [list $res $source] } proc run program { foreach x $program { lassign $x op val switch -exact -- $op { INC { tape::inc $val } MOVE { tape::move $val } PRINT { puts -nonewline [format %c [tape::current]] flush stdout } LOOP { while {[tape::current] > 0} { run $val } } } } return } } proc main argv { lassign $argv filename set f [open $filename] lassign [::bf::parse [split [read $f] {}]] program close $f set ::bf::tape::data 0 set ::bf::tape::pos 0 ::bf::run $program } main $argv