CloudFlare suffered a massive security issue affecting all of its customers, including Rosetta Code. All passwords not changed since February 19th 2017 have been expired, and session cookie longevity will be reduced until late March.--Michael Mol (talk) 05:15, 25 February 2017 (UTC)

Execute Brain****/Clojure

From Rosetta Code
Execute Brain****/Clojure is an implementation of Brainf***. Other implementations of Brainf***.
Execute Brain****/Clojure is part of RCBF. You may find other members of RCBF at Category:RCBF.

This is a brainfuck interpreter in Clojure which completely refrains from mutating any state. The nature of Clojure (namely, that hashes and sets are functions) facilitates a rather clean loop/recur approach. At each iteration, the components of the execution model (the program counter, byte pointer, and tape) are "redefined" as the application of some function (informed by the current instruction) to their previous value.

(defn pair-brackets [indexed]
"indexed is a sequence of 2-tuples of the form [index instruction].
This is reduced into a hash of indices that is used to inform jumps."

(fn [pairs cur]
(condp = (cur 1)
\[ (merge-with conj pairs {:pend (cur 0)}) ; new pending open bracket
\] (merge pairs
{(first (pairs :pend)) (cur 0) ; store both
(cur 0) (first (pairs :pend)) ; directions
 :pend (pop (pairs :pend))}) ; no longer pending
{:pend ()} indexed))
(defn brainfuck [insns]
[valid (set "[]<>-+.,")
program (vec (keep #(valid %) insns)) ; sets are functions of their values
jumps (pair-brackets
(map vector (range) program))]
[pc 0 ; program counter
bp 0 ; byte pointer
tape {}]
(if (< pc (count program))
(let [insn (program pc)
cur (tape bp 0)]
(if (= \. insn)
(print (char cur)))
; program counter
((cond ; use jumps hash as the function if applicable, otherwise inc
(and (= \[ insn) (= 0 cur)) jumps
(and (= \] insn) (not= 0 cur)) jumps
 :else inc) pc)
; byte pointer
(({\< dec \> inc} insn identity) bp) ; function hash with fallback
; tape
(#{\- \+} insn)
(merge tape {bp (({\- dec \+ inc} insn) cur)})
(= \, insn)
(merge tape {bp (. System/in read)})
 :else tape)))))))
(-> *command-line-args*
last slurp brainfuck)
$ echo "(> fvzcyr rnfl)" | lein exec bf.clj
(> simple easy)