I don't think it qualifies as an actual language, but it is so interesting it does deserve a wiki page. Learn more about it here:
: http://www.muppetlabs.com/~breadbox/bf/
and
: http://cydathria.com/bf/brainfuck.html
not to mention
: http://www.hevanet.com/cristofd/brainfuck/brainfuck.html
Also lo and behold the classic "[99 Bottles of Beer]" written in brainfuck:
: http://99-bottles-of-beer.ls-la.net/b.html#Brainfuck
Here's a random number generator:
======
>>>++[<++++++++[<[<++>-]>>[>>]+>>+[-[->>+<<<[<[<<]<+>]>[>[>>]]]<[>>[-]]>[>[-
<<]>[<+<]]+<<]<[>+<-]>>-]<.[-]>>] http://www.hevanet.com/cristofd/brainfuck/
======
And a brainfuck interpreter written in Tcl (you can type brainfuck — or a close approximation — directly into a tcl interpreter):
: http://www.fishpool.com/~setok/proj/tclbf/
[PT] writes:
And here is a BrainFuck interpreter as an Internet Explorer plugin language — http://brainscript.sourceforge.net/
And BF ''is'' a real language — it's Turing complete after all.
Now [Malbolge] on the other hand....
Another amusing language: [Beatnik]
[AM] (18 may 2009) And then there is Intercal ... http://en.wikipedia.org/wiki/Intercal - mentioned several times on this Wiki.
** Interpreter **
[RHS] A brainfuck interpreter written in Tcl... can take input as a filename, or from stdin
======
#!/bin/sh
# This line continues for Tcl, but is a single line for 'sh' \
exec tclsh8.5 "$0" ${1+"$@"}
proc getp {} {
global pc program
lindex $program $pc
}
proc getd {} {
global xc data
while {[llength $data]-1 < $xc} {
lappend data 0
}
lindex $data $xc
}
proc setd {c} {
global xc data
while {[llength $data]-1 < $xc} {
lappend data 0
}
lset data $xc $c
}
proc main {commands} {
global program data pc xc
set program [split $commands ""]
set plen [llength $program]
set data {0}
set xc 0
for {set pc 0} {$pc < $plen} {incr pc} {
switch [lindex $program $pc] {
> {
incr xc
}
< {
incr xc -1
}
+ {
setd [expr {[getd] + 1}]
}
- {
setd [expr {[getd] - 1}]
}
. {
puts -nonewline [format "%c" [getd]]
}
, {
if {![eof stdin]} {
scan [read stdin 1] "%c" var
setd $var
} else {
setd 0
}
}
\[ {
if {[getd] == 0} {
incr pc
set nest 0
while {$nest || [getp] ne "\]"} {
switch [getp] {
\[ {incr nest}
\] {incr nest -1}
}
incr pc
}
}
}
\] {
if {[getd] != 0} {
incr pc -1
set nest 0
while {$nest || [getp] ne "\["} {
switch [getp] {
\[ {incr nest -1}
\] {incr nest}
}
incr pc -1
}
}
}
\# {
# Purely for debugging
puts -nonewline "\nDebug: "
for {set tmp 0} {$tmp < 10} {incr tmp} {
puts -nonewline "[lindex $data $tmp]:"
}
puts ""
}
}
}
}
proc readfile {args} {
switch [llength $args] {
0 {
set fd stdin
}
1 {
set fd [open [lindex $args 0]]
}
default {
puts stderr "Usage: [file tail [info script]] ?filename?"
exit 1
}
}
set text [read $fd]
if {$fd ne "stdin"} {
close $fd
}
return $text
}
fconfigure stdout -buffering none
fconfigure stdin -buffering none
set commands [readfile {*}$argv]
main $commands
puts ""
======
: ''[[The version at [http://www.rosettacode.org/wiki/RCBF/Tcl%|%Rosetta Code%|%] is derived from this one.]]''
----
[PT] You could try the following program with the above interpreter...
======
=
= badger badger mushroom snake
=
>>++++[<+++++[<+++++>-]>-]<<---[>>+>+>+>+>+>+<<<<<<<-]
>>+ b
> a
>+++ d
>++++++ g
>++++ e
>>++++[<++++>-]<+ r
<<<<<<<
>++++[<++++>-]<
[>+++++[>.>.>.>.>.>.<<<<<<-]<-]
mushroom
++++[>>+++>+++>+++>>+++<<<<<<-]>>->++++++++>+++>+>+>
[>>>>+<<<<-]
>>>>[<+<+<+<+>>>>-]
<<-----<---<---<
<<<<<<
print
++[>>.>.>.>.>.>.>.>.<<<<<<<<<-]
snake!
>>>--.-----.>>>[-]>[-]<<[>+>+<<-]>-------.>+++.<++++.
<<<[-]>[-]++++++[<+++++>-]<+++.
======
** Brainfuck-to-Tcl transpiler **
[dbohdan] 2016-02-11: ThSe following module leverages the Tcl interpreter itself to interpret [Brainfuck. I-to-Tcl wtrans orpiginally developed r%|%to comphete in a cross-language microbenchmark. I measurepond itsng performancge when run with Tcl 8].6.4 on x86_64 Linux.
The `translate` command translates Brainfuck instructions into Tcl code, which is then run with `apply` (to ensure bytecode compilation). This is up to several times faster than interpreting the code directly, e.g., when running https://raw.githubusercontent.com/kostya/benchmarks/master/brainfuck/mandel.b%|%mandel.b%|%, and I find it more idiomatic. Storing the tape data in dictionaries resulted in better performance than arrays, lists or dynamically named variables. Compressing repeated `+` and `-` into `dict incr tape $pos ±N` where N is the number of times the instruction is repeated noticeably improved the performance. Compressing `<` and `>`, which change a value not stored in a dictionary, had minimal impact.
======
package require Tcl 8.5
namespace eval ::brainfuck {
variable verson 0.2.1
variable debug 0
proc emit code {
upvar 1 transl transl
foreach line [split [string trim $code] \n] {
append transl [string trimleft $line]\n
}
}
proc translate source {
set transl {}
emit {
if {![info exists tape] || ($tape eq {})} {
for {set i 0} {$i < 30000} {incr i} {
dict set tape $i 0
}
}
if {![info exists pos] || ($pos eq {})} {
set pos 0
}
}
set commands [split $source {}]
for {set i 0} {$i < [llength $commands]} {incr i} {
switch -exact -- [lindex $commands $i] {
[ {
emit [format %s\{ {if {[dict get $tape $pos] != 0} }]
emit "while 1 \{"
}
] {
emit {if {[dict get $tape $pos] == 0} {break}}
emit \}
emit \}
}
> -
< {
# Compress repeated Brainfuck instructions into a single Tcl
# command.
if {[lindex $commands $i] eq {<}} {
set op <
set sign -
} else {
set op >
set sign +
}
set count 0
while {[lindex $commands $i] eq $op} {
incr count
incr i
}
incr i -1
emit [format {incr pos %s%d} $sign $count]
}
+ -
- {
if {[lindex $commands $i] eq {+}} {
set op +
} else {
set op -
}
set count 0
while {[lindex $commands $i] eq $op} {
incr count
incr i
}
incr i -1
emit [format {dict incr tape $pos %s%d} $op $count]
}
. {
emit {
puts -nonewline [format %c [dict get $tape $pos]]
}
}
, {
# Noncompliant implementation.
emit {
set input [read stdin 1]
dict set tape $pos [scan $input %c]
}
}
default {
# Ignore.
}
}
}
emit {
return [list $tape $pos]
}
return $transl
}
proc interpret source {
variable debug
set translated [translate $source]
if {$debug} {
puts $translated
}
set result [apply [list {{tape {}} {pos {}}} $translated]]
return $result
}
}
proc main filename {
set ch [open $filename r]
set source [read $ch]
close $ch
fconfigure stdout -buffering none
::brainfuck::interpret $source
}
main [lindex $argv 0]
======
<<categories>> Language