Execute Brain****/Common Lisp: Difference between revisions
m
Fixed syntax highlighting.
(remove indentation that shows up in string) |
m (Fixed syntax highlighting.) |
||
(4 intermediate revisions by 3 users not shown) | |||
Line 1:
{{implementation|Brainf***}}{{collection|RCBF}}
This is an implementation of [[Brainf***]] written in [[Common Lisp]].
<
(program)
(program-counter 0)
(memory (make-array 1 :initial-element 0 :adjustable t))
(memory-pointer 0
(stack))
(defmacro with-bf-slots ((program-sym program-counter-sym
"Macro to replace cumbersome structure slot references with
local lexical macros resembling local variables."
,@body))
(defun adjust-memory (state)
a valid index to the memory array. If it is too large, the array
is extended; if it is negative, the array is extended, its
contents are shifted forward and the memory-pointer is incremented,
by an amount to make the memory ."
(
(cond ((>=
(adjust-array mem (
(let ((extent
(let ((
(
▲ (setf (bf-state-memory state)
(make-array (+ (length old-memory) extent)))▼
(setf (subseq (bf-state-memory state) extent)▼
▲ old-memory))))))
(defun matching-bracket-for (program bracket-index)
(loop with depth
for index
when (>= index (length program))
do (error "unmatched [ bracket")
do (decf depth)▼
until (zerop depth)
finally (return index)))
(defun brainfuck-eval (state &optional (stream *standard-output*))▼
▲ (let ((program (bf-state-program state))
(places nil))▼
(loop while (< (bf-state-program-counter state) (length program)) do▼
(#\+ (incf (elt (bf-state-memory state) (bf-state-memory-pointer state))))▼
(#\- (decf (elt (bf-state-memory state) (bf-state-memory-pointer state))))▼
▲ (#\[ (if (/= 0 (elt (bf-state-memory state) (bf-state-memory-pointer state)))
▲ (push (1- (bf-state-program-counter state)) places)
▲ (matching-bracket-for program (bf-state-program-counter state)))))
(#\] (setf (bf-state-program-counter state) (pop places)))▼
(#\. (write-char (code-char (elt (bf-state-memory state)▼
▲ (bf-state-memory-pointer state)))
▲ stream)))
(incf (bf-state-program-counter state)))))▼
(defun
(with-bf-slots (program pc mem ptr stack) state
(case (aref program pc)
(#\+ (incf (aref mem ptr)))
(#\[ (if (/= 0 (aref mem ptr))
(push (1- pc) stack)
(defun brainfuck-compile-guts (program &optional (start 0) (until-bracket nil))
(loop for insn from start below (length program)
appending (case (aref program insn)
(#\+ `((incf (aref mem ptr))))
(#\- `((decf (aref mem ptr))))
(#\[ (let ((end (matching-bracket-for program insn)))
(prog1
`((do () ((= 0 (aref mem ptr)))
,@(brainfuck-compile-guts program (1+ insn) end)))
(setf insn end))))
(#\] (if until-bracket
(if (= until-bracket insn)
(loop-finish)
(error "internal problem matching brackets"))
(error "extra ] bracket")))
(#\. `((write-char (code-char (aref mem ptr)) stream))))))
(defun brainfuck-compile (program)
(let ((state (make-bf-state :program ,program)))
(with-bf-slots (program pc mem ptr stack) state
,@(brainfuck-compile-guts program))
(values)))))
(defun bf (program)
(if (and (not (zerop (length program)))
(char= #\! (aref program 0)))
(funcall (brainfuck-compile program))
(defun bf-repl ()
"read-eval-print loop for bf. Code prefixed with ! is compiled, otherwise interpreted"
(loop do (fresh-line)
(princ "BRAINFUCK> ")
(bf (read-line))))</
|