We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

BF (BestCoder)

From Esolang
Jump to navigation Jump to search
Not to be confused with brainfuck. For the category-theoretic object, see BF (category).

BF is brainfuck but weird, based upon a deliberately confounding transposition of the instruction identifiers, thus forming a trivial brainfuck substitution.

Commands

BF's equivalence with brainfuck capacitates the following unambiguous mapping betwixt the two cognate languages:

BF brainfuck Description
- > Move the cell pointer to the right.
+ < Move the cell pointer to the left.
< + Increment the memory cell at the cell pointer.
> - Decrement the memory cell at the cell pointer.
[ . Output the character signified by the cell at the cell pointer.
] , Input a character and store it in the cell at the cell pointer.
. [ Jump past the matching ] if the cell at the pointer equals zero (0).
, ] Jump back to the matching [ if the cell at the pointer does not equal zero (0).

Examples

Hello, World!

This program issues the message “Hello, World!” to the standard output:

<.>>->.--<->>>>>++,+>>+>>>,->[---<[--[[<<<.[-,++++[<<<[>>>>>>[++>[----<[

Cat Program

A repeating cat program, which terminates on a null character input, shall be presented:

].[],

Truth-Machine

A truth-machine is adduced alow:

<<<<<<<<<--]++.>-<<<<<+,-<<<.->+>,--<<<<<.-<<<<<<<<<<+>,->++.--[++,-->[

Interpreter

An interpreter implementation in Common Lisp shall be adduced:

(deftype octet ()
  "An unsigned byte value in the closed integral interval [0, 255]."
  '(unsigned-byte 8))

;;; -------------------------------------------------------

(declaim (type simple-string *program*))
(declaim (type fixnum        *ip*))
(declaim (type character     *current-token*))
(declaim (type boolean       *program-is-exhausted-p*))
(declaim (type unsigned-byte *tape*))
(declaim (type integer       *cell-pointer*))
(declaim (type integer       *lowest-accessed-cell-index*))
(declaim (type T             *byte-selector-the-current-cell*))
(declaim (type boolean       *current-cell-contains-zero-p*))
(declaim (type character     +NULL-CHARACTER+))

;;; -------------------------------------------------------

(defparameter *program* ""
  "The BF source code to execute.")

(defparameter *ip* 0
  "The instruction pointer (IP) position into the \"*program*\".")

(define-symbol-macro *current-token*
  (the character
    (schar *program* *ip*)))

(define-symbol-macro *program-is-exhausted-p*
  (the boolean
    (not (array-in-bounds-p *program* *ip*))))

(defparameter *tape* #b00000000
  "The memory tape as an integer-encoded bit sequence, each attiguous
   catena of eight bits forming a cell's unsigned byte representation,
   the lowest bits mapping to the cell amenable to the smallest address,
   increasing in the subscripts towards the most significant bit (MSB)
   positions.")

(defparameter *cell-pointer* 0
  "The current cell pointer position.")

(defparameter *lowest-accessed-cell-index* 0
  "The bit offset into the \"*tape*\"'s binary sequence which
   corresponds to the unsigned byte's lowest significant bit (LSB) in
   the cell designated by the \"*cell-pointer*\".")

(define-symbol-macro *byte-selector-for-the-current-cell*
  (the T
    (byte 8
      (* (- *cell-pointer* *lowest-accessed-cell-index*) 8))))

(define-symbol-macro *current-cell-contains-zero-p*
  (the boolean (not (null (zerop (current-cell-value))))))

(defconstant +NULL-CHARACTER+ (code-char 0)
  "Represents the \"null character\", amenable to the ASCII code zero
   (0), in an implementation-independent manner.")

;;; -------------------------------------------------------

(defun move-the-cell-pointer-left ()
  "Translates the cell pointer one step to the left and returns no value."
  (decf *cell-pointer*)
  (when (< *cell-pointer* *lowest-accessed-cell-index*)
    (psetf *lowest-accessed-cell-index* *cell-pointer*
           *tape*                       (ash *tape* 8)))
  (values))

;;; -------------------------------------------------------

(defun move-the-cell-pointer-right ()
  "Translates the cell pointer one step to the right and returns no value."
  (incf *cell-pointer*)
  (values))

;;; -------------------------------------------------------

(defun current-cell-value ()
  "Returns the unsigned byte value stored in the tape's current cell."
  (the octet (ldb *byte-selector-for-the-current-cell* *tape*)))

;;; -------------------------------------------------------

(defun (setf current-cell-value) (new-value)
  "Stores the NEW-VALUE in the tape's current cell and returns no value."
  (declare (type integer new-value))
  (setf (ldb *byte-selector-for-the-current-cell* *tape*)
        (mod new-value 256))
  (values))

;;; -------------------------------------------------------

(defun locate-the-matching-back-jump-point (&aux (start-point *ip*))
  "Moves the instruction pointer (IP) forward to the matching back
   jump instruction and returns no value."
  (declare (type fixnum start-point))
  (incf *ip*)
  (loop with nesting-level of-type fixnum = 0
    if *program-is-exhausted-p* do
      (error "Unmatched forward jump point at position ~d." start-point)
    else if (char= *current-token* #\,) do
      (if (zerop nesting-level)
        (loop-finish)
        (decf nesting-level))
    else if (char= *current-token* #\.) do
      (incf nesting-level)
    end
    do (incf *ip*))
  (values))

;;; -------------------------------------------------------

(defun locate-the-matching-forward-jump-point (&aux (start-point *ip*))
  "Moves the instruction pointer (IP) backward to the matching forward
   jump instruction and returns no value.."
  (declare (type fixnum start-point))
  (decf *ip*)
  (loop with nesting-level of-type fixnum = 0
    if *program-is-exhausted-p* do
      (error "Unmatched back jump point at position ~d." start-point)
    else if (char= *current-token* #\.) do
      (if (zerop nesting-level)
        (loop-finish)
        (decf nesting-level))
    else if (char= *current-token* #\,) do
      (incf nesting-level)
    end
    do (decf *ip*))
  (values))

;;; -------------------------------------------------------

(defun interpret-BF (code)
  "Interprets the piece of BF source CODE and returns no value."
  (declare (type string code))
  (psetf *program*                    (coerce code 'simple-string)
         *ip*                         0
         *tape*                       #b00000000
         *cell-pointer*               0
         *lowest-accessed-cell-index* 0)
  (loop until *program-is-exhausted-p* do
    (case *current-token*
      (#\<  (incf (current-cell-value)))
      (#\>  (decf (current-cell-value)))
      (#\+  (move-the-cell-pointer-left))
      (#\-  (move-the-cell-pointer-right))
      (#\[  (format T "~c" (code-char (current-cell-value))))
      (#\]  (format T "~&>> ")
            (finish-output)
            (setf (current-cell-value)
                  (char-code (read-char NIL NIL +NULL-CHARACTER+)))
            (clear-input))
      (#\.  (when *current-cell-contains-zero-p*
              (locate-the-matching-back-jump-point)))
      (#\,  (unless *current-cell-contains-zero-p*
              (locate-the-matching-forward-jump-point)))
      (otherwise NIL))
    (incf *ip*))
  (values))