Execute Brain****/Common Lisp: Difference between revisions

m
Fixed syntax highlighting.
m (<code>)
m (Fixed syntax highlighting.)
 
(9 intermediate revisions by 7 users not shown)
Line 1:
{{implementation|Brainf***}}{{collection|RCBF}}
=={{header|Common Lisp}}==
 
This is an implementation of [[Brainf***]] written in [[Common Lisp]].
<code lisp>(defstruct bf-state
 
<codesyntaxhighlight lang="lisp">(defstruct bf-state
(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
(defun adjust-memory (state)
(cond ((>= (bf-state memory-sym memory-pointer state)-sym
(array-dimension (bf-state-memory state) 0) stack-sym)
(adjust-array (bf obj-state-memoryexpr &body statebody)
"Macro to replace cumbersome structure slot references with
(1+ (bf-state-memory-pointer state))
local lexical macros resembling local variables."
:initial-element 0))
`(symbol-macrolet ((<,program-sym (bf-state-memoryprogram ,obj-pointer stateexpr) 0)
(let ((extent (,program-counter-sym (bf-state-memoryprogram-pointercounter state)),obj-expr))
(incf,memory-sym (bf-state-memory-pointer state,obj-expr) extent)
(let ((old-memory (copy,memory-seqpointer-sym (bf-state-memory-pointer state)),obj-expr))
(setf,stack-sym (bf-state-memorystack state,obj-expr)))
,@body))
(make-array (+ (length old-memory) extent)))
(setf (subseq (bf-state-memory state) extent)
old-memory))))))
 
(defun adjust-memory (state)
"Modifies memory and memory-pointer such that memory-pointer is
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 ."
(with-bf-slots (program pc mem ptr stack) state
(cond ((>= ptr (length mem))
(adjust-array mem (1+ ptr) :initial-element 0))
((placesminusp nil)ptr)
(let ((extent (- ptr)))
(incf ptr extent)
(let ((old-memory (copy-seq mem)))
(setf mem (make-array (+ (length old-memory) extent)))
(setf (subseq mem extent) old-memory)))))))
(defun matching-bracket-for (program bracket-index)
(letloop with ((depth 0))= 1
(loop for index := bracket-for index thenfrom (1+ bracket-index)
when (>= index (length program))
do (error 'fail"unmatched [ bracket")
whendo (char= #\[case (eltaref program index))
do (#\[ (incf depth))
when (char= (#\] (elt programdecf indexdepth)))
dountil (decfzerop depth)
untilfinally (= depthreturn 0index)))
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
(case (elt program (bf-state-program-counter state))
(#\+ (incf (elt (bf-state-memory state) (bf-state-memory-pointer state))))
(#\- (decf (elt (bf-state-memory state) (bf-state-memory-pointer state))))
(#\> (incf (bf-state-memory-pointer state)) (adjust-memory state))
(#\< (decf (bf-state-memory-pointer state)) (adjust-memory state))
(#\[ (if (/= 0 (elt (bf-state-memory state) (bf-state-memory-pointer state)))
(push (1- (bf-state-program-counter state)) places)
(setf (bf-state-program-counter state)
(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 bf (program) (brainfuck-eval (make-bf-state :program&optional program)(stream *standard-output*))
(with-bf-slots (program pc mem ptr stack) state
(loop while (< (bf-state-program-counter state)pc (length program)) do
(case (aref program pc)
(#\+ (incf (aref mem ptr)))
(#\- (decf (aref mem ptr)))
(#\+> (incf (elt (bf-state-memory stateptr) (bf-stateadjust-memory-pointer state))))
(#\-< (decf (elt (bf-state-memory stateptr) (bf-stateadjust-memory-pointer state))))
(#\[ (if (/= 0 (aref mem ptr))
(push (1- (bf-state-program-counter state)pc) placesstack)
(setf pc (bfmatching-statebracket-for program-counter statepc))))
(#\] (setf (bf-state-program-counter state)pc (pop placesstack)))
(#\. (write-char (code-char (eltaref (bf-state-memorymem stateptr)) stream)))
(incf pc))))
 
(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))))
(#\> `((incf ptr) (1+ (bf-stateadjust-memory-pointer state)))
(setf#\< `(subseq(decf ptr) (bf-stateadjust-memory state) extent))
(#\[ (let ((end (matching-bracket-for program (bf-state-program-counter state))insn)))
stream))) (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)
(defuncompile brainfuck-evalnil `(statelambda (&optional (stream *standard-output*))
(let ((programstate (make-bf-state- :program state,program)))
(with-bf-slots (program pc mem ptr stack) state
,@(bf-statebrainfuck-memorycompile-pointerguts state)program))
old-memory) (values)))))
 
(defun bf (program)
(if (and (not (zerop (length program)))
(char= #\! (aref program 0)))
(funcall (brainfuck-compile program))
(incfbrainfuck-eval (make-bf-state- :program-counter state)program))))
(defun bf-repl ()
"read-eval-print loop for bf. Code prefixed with ! is compiled, otherwise interpreted"
(loop do (fresh-line)
(princ "BRAINFUCK> ")
(brainfuck-eval (make-bf-state :program (read-line)))))</codesyntaxhighlight>
9,476

edits