Execute Brain****: Difference between revisions
Content added Content deleted
m (moved RCBF to Execute Brain****) |
|||
Line 20: | Line 20: | ||
[[/C++|Implementation in C++]]. |
[[/C++|Implementation in C++]]. |
||
=={{header|Clojure}}== |
|||
<lang clojure>(ns brainfuck) |
|||
(def *input*) |
|||
(def *output*) |
|||
(defstruct data :ptr :cells) |
|||
(defn inc-ptr [next-cmd] |
|||
(fn [data] |
|||
(next-cmd (assoc data :ptr (inc (:ptr data)))))) |
|||
(defn dec-ptr [next-cmd] |
|||
(fn [data] |
|||
(next-cmd (assoc data :ptr (dec (:ptr data)))))) |
|||
(defn inc-cell [next-cmd] |
|||
(fn [data] |
|||
(let [ptr (:ptr data) |
|||
cells (:cells data)] |
|||
(next-cmd (assoc data :cells (assoc cells ptr (inc (get cells ptr 0)))))))) |
|||
(defn dec-cell [next-cmd] |
|||
(fn [data] |
|||
(let [ptr (:ptr data) |
|||
cells (:cells data)] |
|||
(next-cmd (assoc data :cells (assoc cells ptr (dec (get cells ptr 0)))))))) |
|||
(defn output-cell [next-cmd] |
|||
(fn [data] |
|||
(set! *output* (conj *output* (get (:cells data) (:ptr data) 0))) |
|||
(next-cmd data))) |
|||
(defn input-cell [next-cmd] |
|||
(fn [data] |
|||
(let [[input & rest-input] *input*] |
|||
(set! *input* rest-input) |
|||
(next-cmd (assoc data :cells (assoc (:cells data) (:ptr data) input)))))) |
|||
(defn if-loop [next-cmd loop-cmd] |
|||
(fn [data] |
|||
(next-cmd (loop [d data] |
|||
(if (zero? (get (:cells d) (:ptr d) 0)) |
|||
d |
|||
(recur (loop-cmd d))))))) |
|||
(defn terminate [data] data) |
|||
(defn split-cmds [cmds] |
|||
(letfn [(split [[cmd & rest-cmds] loop-cmds] |
|||
(when (nil? cmd) (throw (Exception. "invalid commands: missing ]"))) |
|||
(case cmd |
|||
\[ (let [[c l] (split-cmds rest-cmds)] |
|||
(split c (str loop-cmds "[" l "]"))) |
|||
\] [(apply str rest-cmds) loop-cmds] |
|||
(split rest-cmds (str loop-cmds cmd))))] |
|||
(split cmds ""))) |
|||
(defn compile-cmds [[cmd & rest-cmds]] |
|||
(if (nil? cmd) |
|||
terminate |
|||
(case cmd |
|||
\> (inc-ptr (compile-cmds rest-cmds)) |
|||
\< (dec-ptr (compile-cmds rest-cmds)) |
|||
\+ (inc-cell (compile-cmds rest-cmds)) |
|||
\- (dec-cell (compile-cmds rest-cmds)) |
|||
\. (output-cell (compile-cmds rest-cmds)) |
|||
\, (input-cell (compile-cmds rest-cmds)) |
|||
\[ (let [[cmds loop-cmds] (split-cmds rest-cmds)] |
|||
(if-loop (compile-cmds cmds) (compile-cmds loop-cmds))) |
|||
\] (throw (Exception. "invalid commands: missing [")) |
|||
(compile-cmds rest-cmds)))) |
|||
(defn compile-and-run [cmds input] |
|||
(binding [*input* input *output* []] |
|||
(let [compiled-cmds (compile-cmds cmds)] |
|||
(println (compiled-cmds (struct data 0 {})))) |
|||
(println *output*) |
|||
(println (apply str (map char *output*))))) |
|||
</lang> |
|||
<lang clojure>brainfuck> (compile-and-run "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>." []) |
|||
{:ptr 4, :cells {4 10, 3 33, 2 100, 1 87, 0 0}} |
|||
[72 101 108 108 111 32 87 111 114 108 100 33 10] |
|||
Hello World! |
|||
nil |
|||
</lang> |
|||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||