Recently Written · git

LispBrain

The best Brainfuck debugger available, if you know how the Common Lisp debugger works. Uses Common Lisp's ease of debugging to make debugging Brainfuck code easy. Almost entirely useless.

git clone https://github.com/equwal/LispBrain

Log | Files | Refs


commit 5a1740dbc13f98e5012b57f6f9110d061a87ffd3
Spenser Truex <struex0@gmail.com>
2016-02-15 11:45:37 -0800

Sweeping changes

 README.md                 | 32 ++++++++++++++++++++++++++++++-
 lispfuck.asd => brain.asd |  2 +-
 interpreter.lisp          | 48 +++++++++++++++++++++++++----------------------
 packages.lisp             |  2 +-
 4 files changed, 59 insertions(+), 25 deletions(-)
diff --git a/README.md b/README.md
index 3c23bbb..d28b259 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,9 @@
 # Lisp Fuck
 Lisp Fuck is a simple brainfuck interpreter written in Common Lisp. It has only been tested on SBCL. Any testing information on other systems is much appreciated.
 
+#Why Is That Necessary?
+This provides the ability to debug your brainfuck code using common lisp's rich debugging environment, or integrate brainfuck into your lisp code should that be interesting to you.
+
 #Brainfuck
 Brainfuck is an esoteric programming language that works on a theoretical byte tape. The commands are:
 ```
@@ -24,11 +27,13 @@ These can be combined into a string such as the following "Hello World!#\Newline
 #How to use:
 Store this project's code in the common-lisp directory under your home directory. Then it may be loaded like this:
 ```
-> (asdf:load-system "lispfuck")
+> (asdf:load-system "brain")
 ```
 The external functions need to be **used**, so execute this command.
 ```
 > (use-package :cl-brainfuck)
+or alternatively the brainfuck functions may be called using the brain:function notation:
+> (brain:fuck "[Put your code in the string]")
 ```
 Your brainfuck interpreter is now loaded!
 
@@ -50,6 +55,31 @@ Finally, there is a slightly more profane alias for the `interpret` function:
 ```
 > (fuck "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.F+++++++++++++++.U------------------.C++++++++.K")
 "FUCK"
+;; Also:
+> (brain:fuck "[This is a loop comment.]")
+```
+Debugging brainfuck code can be done using all the normal lisp functions `step`, `trace`, `time`, etc., but require the user to understand how the internal code works. For this reason there is no tutorial on how to properly debug your brainfuck code, just a couple examples.
+
+Suppose you want to make the tape only 10 bytes long:
+```
+> (in-package :brain)
+> (setf *tape-size-default* 10) ;Sets the tape to only elements 0 to 9
+> (reset-globals) ;Resets the tape, pointer, and a few other things
+> *tape*
+10
+> *pointer*
+5
+```
+Suppose you want to find information about the + and - operations:
+```
+> (trace incf-byte decf-byte)
+> (fuck "+-")
+;;;; This text following is implementation dependent, and looks like THIS on SBCL
+  0: (INCF-BYTE)
+  0: INCF-BYTE returned 1
+  0: (DECF-BYTE)
+  0: DECF-BYTE returned 0
+""
 ```
 #TODO:
 - Test on other implementations and operating systems.
diff --git a/lispfuck.asd b/brain.asd
similarity index 98%
rename from lispfuck.asd
rename to brain.asd
index 5b14d9d..103830d 100644
--- a/lispfuck.asd
+++ b/brain.asd
@@ -8,7 +8,7 @@
 (defpackage :cl-brainfuck-system (:use :asdf :cl))
 (in-package :cl-brainfuck-system)
 
-(defsystem lispfuck
+(defsystem brain
   :name "lispfuck"
   :author "Spenser Max Truex"
   :version "1.0"
diff --git a/interpreter.lisp b/interpreter.lisp
index 6efa4f3..6dc0af7 100644
--- a/interpreter.lisp
+++ b/interpreter.lisp
@@ -13,7 +13,7 @@
 ;;;; OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
 ;;;; OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THIS BRAINFUCK SOFTWARE OR THE USE OR OTHER DEALINGS IN THIS 
 ;;;; BRAINFUCK SOFTWARE.
-(in-package :cl-brainfuck)
+(in-package :brain)
 (defparameter *tape-size-default* 30000
   "The size of the tape, in bytes, used to store each byte")
 
@@ -39,6 +39,7 @@
 (defun pointer-default ()
   "Get the value to  set the pointer back to."
   (floor (/ *tape-size-default* 2)))
+
 (defvar *pointer* (pointer-default)
   "The pointer location for the tape. Starts near the middle.")
 
@@ -48,8 +49,11 @@
   (setf *pointer* (pointer-default))
   (setf *output* ""))
 
+(defun wrap-pointer ()
+  (cond ((= *pointer* *tape-size-default*) (setf *pointer* 0))
+		((= *pointer* -1) (setf *pointer* (1- *tape-size-default*)))))
 (defmacro byte-value ()
-  `(elt *tape* *pointer*))
+  `(aref *tape* *pointer*))
 
 (defun remove-first (string)
   (if (= 1 (length string))
@@ -75,10 +79,10 @@
 (defun first-elt (string)
   (elt string 0))
 
-(defun ascii-to-integer (char)
+(defun ascii->integer (char)
   (char-code char))
 
-(defun integer-to-ascii (num)
+(defun integer->ascii (num)
   (code-char num))
 
 (defun goto-aux (current-position
@@ -102,21 +106,23 @@
   (goto-aux position 0))
 
 (defun right-shift ()
-  "Move to the next byte to the \"right\""
-  (setf *pointer* (1+ *pointer*)))
+  "Move to the next byte to the 'right'"
+  (incf *pointer*)
+  (wrap-pointer))
 
 (defun left-shift ()
-  "Move to the next byte to the \"left\""
-  (setf *pointer* (1- *pointer*)))
+  "Move to the next byte to the 'left'"
+  (decf *pointer*)
+  (wrap-pointer))
 
 (defun print-this-byte ()
   (setf *output* (concatenate 'string
 			      *output*
-			      (vector (integer-to-ascii (byte-value))))))
+			      (vector (integer->ascii (byte-value))))))
 
 (defun read-this-byte ()
   (setf (byte-value)
-	(ascii-to-integer (read-char))))
+	(ascii->integer (read-char))))
 
 (defun one-off-fuck (position)
   "Run a single first brainfuck-char."
@@ -132,7 +138,7 @@
     (#\< (left-shift))))
 
 (defun skip-loop-aux (position depth)
-  (let ((this (elt *brainfuck* position)))
+  (let ((this (char *brainfuck* position)))
     (if (char= #\[ this)
 	(skip-loop-aux (1+ position) (1+ depth))
 	(if (char= #\] this)
@@ -144,23 +150,21 @@
 (defun skip-loop (position)
   (skip-loop-aux position 0))
 
-(defun interpret-fuck-aux (position)
-  (loop
-     until (= (length *brainfuck*) position)
-     do (handler-case (one-off-fuck position)
-	  (end-of-loop () (setf position
-				(1- (goto position))))
-	  (open-loop-at-zero () (setf position
-				      (1- (skip-loop position)))))
-     do (setf position (1+ position))))
-
 (defun interpret (brainfuck-string)
   "Interpret the brainfuck"
   (reset-globals)
   (setf *brainfuck* brainfuck-string)
-  (interpret-fuck-aux 0)
+  ;; Loop over each character in the string
+  (loop for position to (1- (length *brainfuck*))
+     do (handler-case (one-off-fuck position)
+	  ;; Handles looping with the condition system
+	  (end-of-loop () (setf position
+				(1- (goto position))))
+	  (open-loop-at-zero () (setf position
+				      (1- (skip-loop position))))))
   *output*)
 
 (defun fuck (brainfuck-string)
   "An alias for the interpret function"
   (interpret brainfuck-string))
+
diff --git a/packages.lisp b/packages.lisp
index 6dbc64d..91b907f 100644
--- a/packages.lisp
+++ b/packages.lisp
@@ -6,7 +6,7 @@
 
 ;;;; THE BRAINFUCK SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THIS BRAINFUCK SOFTWARE OR THE USE OR OTHER DEALINGS IN THIS BRAINFUCK SOFTWARE.
 (in-package :cl-user)
-(defpackage :cl-brainfuck
+(defpackage :brain
   (:use :cl)
   (:export :interpret
 	   :fuck))