Braisnack

From Esolang
Jump to navigation Jump to search

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)))))