brainappend
Jump to navigation
Jump to search
brainappend is a brainfuck derivative by User:Joaozin003, partly inspired by Vague where the braces ([
and ]
) append their contents to the source code (including themselves). This makes looping much more difficult.
Instructions
Instruction | Command |
---|---|
+, -, <, >, , and . |
Same as brainfuck |
] |
If the value of the current memory cell is not 0, then append the source code enclosed by this and the matching [ , including the braces themselves, e.g. [>] appends [>] when ] gets ran
|
[ |
If the value of the current memory cell is 0, then jump to the matching ] .
|
Examples
Cat program (NUL-terminated)
,[.,]
Gets a character, then appends [.,]
to the source code if it is not NUL.
Truth-machine
The following program implements a truth-machine:
,.>+++++++++++++++++++++++++++++++++++++++++++++++++ <------------------------------------------------[>.<]
See also
Implementation
An implementation in Common Lisp shall be produced below:
(deftype hash-table-of (&optional (key-type T) (value-type T)) "Defines a hash table composed of entries whose key match the KEY-TYPE and whose values assume the VALUE-TYPE." (let ((predicate (gensym))) (declare (type symbol predicate)) (setf (symbol-function predicate) #'(lambda (candidate) (declare (type T candidate)) (and (hash-table-p candidate) (loop for key of-type T being the hash-keys in (the hash-table candidate) using (hash-value value) always (and (typep key key-type) (typep value value-type)))))) `(satisfies ,predicate))) (deftype octet () "Defines an unsigned byte as an integer in the range [0, 255]." '(unsigned-byte 8)) (deftype memory () "Defines the program memory as a hash table-based vector of unsigned bytes." '(hash-table-of integer octet)) (defun make-memory () "Returns a new memory instance." (the memory (make-hash-table :test #'eql))) (defun cell-value-at (memory index) "Returns the value stored in the MEMORY cell at the INDEX." (declare (type memory memory) (type integer index)) (the octet (gethash index memory 0))) (defun (setf cell-value-at) (new-value memory index) "Stores the NEW-VALUE in the MEMORY cell at the INDEX and returns no value." (declare (type memory memory) (type integer index)) (setf (gethash index memory 0) (mod new-value 256)) (values)) (defun find-left-bracket (code start) "Commencing with the START index into the CODE, returns the position of the matching \"[\" token, or signals an error of an unspecified type upon its disrespondency." (declare (type string code) (type fixnum start)) (the fixnum (loop with nesting-level of-type fixnum = 0 for position of-type fixnum from start downto 0 for token of-type character = (char code position) if (and (char= token #\[) (zerop nesting-level)) do (return position) else if (and (char= token #\[) (/= nesting-level 0)) do (decf nesting-level) else if (char= token #\]) do (incf nesting-level) end finally (error "No matching left bracket (\"[\") found.")))) (defun find-right-bracket (code start) "Commencing with the START index into the CODE, returns the position of the matching \"]\" token, or signals an error of an unspecified type upon its disrespondency." (declare (type string code) (type fixnum start)) (the fixnum (loop with nesting-level of-type fixnum = 0 for position of-type fixnum from start below (fill-pointer code) for token of-type character = (char code position) if (char= token #\[) do (incf nesting-level) else if (and (char= token #\]) (zerop nesting-level)) do (return position) else if (and (char= token #\]) (/= nesting-level 0)) do (decf nesting-level) end finally (error "No matching right bracket (\"]\") found.")))) (defun interpret-brainappend (initial-code) "Interprets the brainappend INITIAL-CODE and returns no value." (declare (type string initial-code)) (let ((code (make-array (length initial-code) :element-type 'character :initial-contents initial-code :adjustable T :fill-pointer T)) (ip 0) (memory (make-memory)) (cell-pointer 0)) (declare (type string code) (type fixnum ip) (type memory memory) (type integer cell-pointer)) (loop while (< ip (fill-pointer code)) do (case (char code ip) (#\+ (incf (cell-value-at memory cell-pointer))) (#\- (decf (cell-value-at memory cell-pointer))) (#\> (incf cell-pointer)) (#\< (decf cell-pointer)) (#\, (format T "~&>> ") (finish-output) (let ((input (read-char NIL NIL #\Null))) (declare (type character input)) (setf (cell-value-at memory cell-pointer) (if (char= input #\Newline) 0 (char-code input)))) (clear-input)) (#\. (write-char (code-char (cell-value-at memory cell-pointer)))) (#\[ (when (zerop (cell-value-at memory cell-pointer)) (setf ip (find-right-bracket code (1+ ip))))) (#\] (unless (zerop (cell-value-at memory cell-pointer)) (let ((start-point (find-left-bracket code (1- ip)))) (declare (type fixnum start-point)) (format code "~a" (subseq code start-point (1+ ip)))))) (otherwise NIL)) (incf ip))) (values))