Braisnack

Braisnack uses the SNACBIT. Every cell starts as peanut butter cracker.
==Commands==
Command	Description
> 	Move the pointer to the next cell
< 	Move the pointer to the previous
+ 	Increment the snack in the cell at the pointer, wrapping around at the edges
- 	Decrement the snack in the cell at the pointer, wrapping around at the edges
[ 	Go to the corresponding ] if the snack in the cell at pointer is peanut butter cracker
] 	Go to the corresponding [ if the snack in the cell at pointer is not peanut butter cracker
. 	Print out the name of the snack in the cell at the pointer
, 	Save the input snack in the cell at the pointer
==Examples==
===Cat===
 ,.
===picklepickledoritotortilla chipapplesauce===
 -..+++++.+.+++.
===Iterative snack printing===
This program prints all SNACBIT states in their natural order by mediation of the jump facility:
 .+[.+]
==Interpreter==
An interpreter implementation in Common Lisp follows:
 (declaim (type (simple-array simple-string (11)) +SNACBIT-STATES+))
 
 (defparameter +SNACBIT-STATES+
 (make-array 11
 :element-type 'string
 :initial-contents
 '("Peanut butter cracker"
 "Cosmic brownie"
 "Cheezit"
 "Cheeto"
 "Dorito"
 "Tortilla chip"
 "Cheese cracker"
 "Potato chip"
 "Applesauce"
 "Peanut butter cup"
 "Pickle")))
 
 (defun normalize-state-number (state-number)
 (declare (type integer state-number))
 (the (integer 1 11) (+ 1 (mod (- state-number 1) 11))))
 
 (defun find-snack-number (input)
 (declare (type string input))
 (the (or null (integer 0 10))
 (position-if
 #'(lambda (probed-snack)
 (declare (type string probed-snack))
 (string-equal (remove #\Space input) (remove #\Space probed-snack)))
 +SNACBIT-STATES+)))
 
 (defun query-snack ()
 (the (or null (integer 0 10))
 (prog ((input NIL)
 (selected-snack NIL))
 (declare (type (or null string) input))
 (declare (type (or null (integer 0 10)) selected-snack))
 query-for-input
 (format T "~&>> ")
 (setf input (read-line NIL NIL ""))
 (clear-input)
 (if (plusp (length input))
 (go check-input)
 (go end))
 check-input
 (setf selected-snack (find-snack-number input))
 (if selected-snack
 (go end)
 (go query-for-input))
 end
 (return selected-snack))))
 
 (defun compute-jump-table (code)
 (declare (type string code))
 (the hash-table
 (loop
 with jump-table of-type hash-table = (make-hash-table :test #'eql)
 with start-points of-type list = NIL
 for token of-type character across code
 and position of-type fixnum from 0 by 1
 do (case token
 (#\[ (push position start-points))
 (#\] (if start-points
 (let ((start-position (pop start-points)))
 (declare (type fixnum start-position))
 (setf (gethash start-position jump-table) position)
 (setf (gethash position jump-table) start-position))
 (error "Unmatched \"]\" at position ~d." position)))
 (otherwise NIL))
 finally
 (if start-points
 (error "Unmatched \"[\"s at positions ~{~d~^, ~}." start-points)
 (return jump-table)))))
 
 (defun interpret-Braisnack (code)
 (declare (type string code))
 (let ((jump-table (compute-jump-table code))
 (memory (make-hash-table :test #'eql))
 (cell-pointer 0))
 (declare (type hash-table jump-table memory))
 (declare (type integer cell-pointer))
 (symbol-macrolet ((current-snack (the (integer 1 11) (gethash cell-pointer memory 1))))
 (loop with ip of-type fixnum = 0 while (< ip (length code)) do
 (case (char code ip)
 (#\> (incf cell-pointer))
 (#\< (decf cell-pointer))
 (#\- (setf current-snack (normalize-state-number (1- current-snack))))
 (#\+ (setf current-snack (normalize-state-number (1+ current-snack))))
 (#\[ (when (= current-snack 1)
 (setf ip (gethash ip jump-table))))
 (#\] (unless (= current-snack 1)
 (setf ip (gethash ip jump-table))))
 (#\. (format T "~&~a" (aref +SNACBIT-STATES+ (1- current-snack))))
 (#\, (let ((new-snack-index (query-snack)))
 (declare (type (or null (integer 0 10)) new-snack-index))
 (when new-snack-index
 (setf current-snack (1+ new-snack-index)))))
 (otherwise NIL))
 (incf ip)))))
Category:LanguagesCategory:2023Category:Brainfuck derivativesCategory:Implemented