// http://tunes.org/~iepos/befreak.html
// Brent Kerby: iepos@tunes.org
// Hilton Campbell: chauchauchau@msn.com
// Setup
K:(0 -1;0 1;1 -1;1 1);N:50
clear:{V::();B::"";J::K 3;C::D::E::!0;Z::R::S::T::0;I::start P;W;}
new:{Y::"";I::0 0;P::(2#N)#" ";clear[]}
open:{if[~_n~f:`4:(`open;`txt;"Open program?");get Y::f]}
get:{P::{x,'((|/c)-c:#:'x)#'" "}@0:x;clear[]}
start:{((|/+x)?1;(|/x)?1)!N}"@"=
save:{if[#Y;Y 0:set[];Save[]]}
Save:{if[~_n~f:`4:(`save;`txt;"Save program!");set Y::f]}
set:{x 0:_dv[{(-+/&\" "=|x)_ x}'P;""]}
edit:{P[y;z]:x;I::start P}
// GUI
W.H:("Befreak"
""
" New: Create an empty program"
" Open: Open a program .."
" Save: Save the current program"
"Save_As: Save the current program as .."
" Next: Execute next step"
" Run: Run the program to completion"
" Clear: Clear stacks, reset instruction pointer to @"
"Reverse: Toggle Reverse bit"
" Play: Step through program at 1 second intervals"
""
"In execution mode, click on a cell to toggle its stop status")
W.H..x:70;W.H..y:17;W.H..l:"Befreak?"
W.J..d:".k.J";W.J..l:"Direction"
W.C..d:".k.C";W.C..l:"Control"
W.D..d:".k.D";W.D..l:"Data"
W.E..d:".k.E";W.E..l:"I/O"
W[.;`e]:0
W.P..d:",:''+.k.P"
W.P..u:{*y}
W.P..t:".k.edit[*_v ._i].|_i"
W.P..e..d:"~.k.Z"
W.P..l..d:".k.Y"
W.P..k:"if[.k.Z;:[(|_i)_in .k.V;.k.V:.k.V _dv|_i;.k.V,:,|_i]]"
W.P..bg..d:".k.W.bg[.k.P;.k.I;.k.R;.k.V]"
W.bg:{[p;i;r;v].[(|2#^p)#(|c)r;|i;:;(c:999900 999999)r]{.[x;|y;:;9900]}/v}
W.Help:"`show$`H;" ;W.Help..c:`button
W.New:".k.new[]" ;W.New..c:`button
W.Open:".k.open[]" ;W.Open..c:`button
W.Save:".k.save[]" ;W.Save..c:`button
W.Save_As:".k.Save[]" ;W.Save_As..c:`button
W.Next:".k.step[]" ;W.Next..c:`button
W.Run:".k.run[]" ;W.Run..c:`button
W.Clear:".k.clear[]" ;W.Clear..c:`button
W.Reverse..d:".k.R" ;W.Reverse..c:`check ;W.Reverse..t:".k.R~:"
W.Play..d:".k.T" ;W.Play..c:`check ;W.Play..t:".k.T~:"
W..c:`form
W..a:((`J`C`D`E;`P);+(`Help`New`Open`Save`Save_As;`Next`Run`Clear`Reverse`Play))
W..l..d:"(::;|:)[.k.R]@\"Befreak!\""
W..x:60;W..y:30
// Timer
\t 1
.t..t:"if[.k.T;.k.step[]]"
// Run to completion
run:{if[~Z;step[]];while[(~I _in V)&Z;step[]]}
// Evaluation step
step:{:["\""=t:P . I;q[];S;s t;a t];if[Z;i[]]}
i:{I[*J]+:J 1;I::I!'^P}
q:{if[S~:;n[]]}
s:{D,:_ic x}
a:{if[~x _in"0123456789";n[]];X[X[;0;R]?x;1]x}
n:{if[#B;if[~#D;D,:0];D[-1+#D]:xor[*|D;0$B];B::""]}
// Control flow (<>^v)
m0:{J::K x;C,:y};m1:{C[-1+#C]~:;R~:;J::K x};m2:{c:~R=*|C;C::-1_ C;J::K x c}
// Boolean operations
vs:(8#2)_vs;b:{2_sv x/vs'(y;z)};xor:b[~=];and:b[&];or:b[|]
// Instruction set
X:((" " ;{})
("()" ;{D,:0})
(")(" ;{:[0~*|D;D::-1_ D;'")"]})
("[]" ;{C,:*|D;D::-1_ D})
("][" ;{D,:*|C;C::-1_ C})
("$$" ;{c:*|C;d:*|D;C::(-1_ C),,d;D::(-1_ D),,c})
("wr" ;{E,:c:*|D;D::-1_ D;`0:_ci c})
("rw" ;{:[#E;do[1;c:*|E;E::-1_ E];c:_ic*0:`];D,:c})
("gp" ;{})
("pg" ;{})
("'`" ;{D[-1+#D]+:1})
("`'" ;{D[-1+#D]-:1})
("+-" ;{D::(-2_ D),{(x+y;y)}. -2#D})
("-+" ;{D::(-2_ D),{(x-y;y)}. -2#D})
("%*" ;{D::(-2_ D),{(_ x%y;x!y;y)}. -2#D})
("*%" ;{D::(-3_ D),{(y+x*z;z)}. -3#D})
("~~" ;{D[-1+#D]:2_sv~vs D@-1+#D})
("&|" ;{D::{(xor[x;and[y;z]];x;y)}. -3#D})
("|&" ;{D::{(xor[x;or[y;z]];x;y)}. -3#D})
("##" ;{D::{(xor[x;y];y)}. -2#D})
("{}" ;{D::(-2_ D),{(2_sv y!vs x;y)}. -2#D})
("}{" ;{D::(-2_ D),{(2_sv(-y)!vs x;y)}. -2#D})
("!!" ;{C[-1+#X]:xor[C[-1+#x];1]})
("==" ;{if[=/-2#D;C[-1+#C]:xor[C[-1+#C];1]]})
("lm" ;{if[-2#D;C[-1+#C]:xor[C[-1+#C];1]]})
("ml" ;{if[>/-2#D;C[-1+#C]:xor[C[-1+#C];1]]})
("ss" ;{D[(#D)-1+!2]:-2#D})
("db" ;{D[(#D)-1+!3]:1!-3#D})
("bd" ;{D[(#D)-1+!3]:-1!-3#D})
("ff" ;{D[(#D)-1+!3]:-3#D})
("cc" ;{D[(#D)- 2+!2]:-1_ -3#D})
("ou" ;{D,:*|-2#D})
("uo" ;{:[=/(|D)0 2;D::-1_ D;'"u"]})
(":;" ;{D,:*|D})
(";:" ;{:[=/2#D;D::-1_ D;'";"]})
("??" ;{R~:})
("@@" ;{Z~:})
("\\\\" ;{J::(K 2 3 0 1)K?J})
("//" ;{J::(K 3 2 1 0)K?J})
(">>" ;{:[0=k:K?J;m0[3;~R];1=k;m0[3;R];2=k;m2 1 0;m1 2]})
("<<" ;{:[0=k:K?J;m0[2;R];1=k;m0[2;~R];2=k;m1 3;m2 0 1]})
("vv" ;{:[0=k:K?J;m2 2 3;1=k;m1 0;2=k;m0[1;R];m0[1;~R]]})
("^^" ;{:[0=k:K?J;m1 1;1=k;m2 3 2;2=k;m0[0;~R];m0[0;R]]}))
X,:((,2#)'$!10),'{B,:x}
// Run
:[#_i;get Y:*_i;new[]]
`show$`W;