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 7e62e4719850f4b5597f23f965e7d33c1094420a
Spenser Truex <struex0@gmail.com>
2016-02-15 19:19:19 -0800

Reader macro, shorter README

 README.md        | 35 +++++++++--------------------------
 interpreter.lisp | 37 +++++++++++++++++++++++++++++++++----
 2 files changed, 42 insertions(+), 30 deletions(-)
diff --git a/README.md b/README.md
index 83dc419..e4c5f69 100644
--- a/README.md
+++ b/README.md
@@ -20,43 +20,27 @@ Any other character is considered a "comment" meaning it does nothing.
 
 These can be combined into a string such as the following "Hello World!" program:
 ```
-> (interpret "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.")
+> #f++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
 "Hello World!
 "
 ```
 #How to use:
 Store this project's code in the ASDF load directory; [ASDF](https://common-lisp.net/project/asdf/) must be installed. Then it may be loaded like this:
 ```
-> (asdf:load-system "brain")
+> (asdf:load-system :brain)
 ```
-The external functions are easier to use when they have been *used*, so execute this command.
+Now there is the choice between `brain:fuck` and the `#F` notation. The #F notation is more concise but does not allow any whitespace in the brainfuck code. Below they are both shown
 ```
-> (use-package :brain)
-or alternatively the brainfuck functions may be called using the brain:[function] notation, without being used:
-> (brain:fuck "[Put your code in the string]")
-```
-Your brainfuck interpreter is now loaded!
-
-You can run a string of brainfuck code with:
-```
-> (interpret "[code]")
-```
-For example:
-```
-> (interpret ".+[.+] Print out all the ascii characters")
+> (brain:fuck ".+[.+] Print out all the ascii characters from 0 to 255")
 
 "�	
 


 


 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„
†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"
-```
-Take note that the `interpret` command returns a string, which allows the brainfuck to be used within other lisp code.
 
-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.]")
+>#f.+[.+] ;Note that this comment is not part of the brainfuck because of the space between it and the brainfuck code.
+"�	
+


+


 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„
†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"
 ```
 Debugging brainfuck code can be done using all the normal Common 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. The user is encouraged to read the Common Lisp source code to get all the features of the Lisp debugging environment in their brainfuck.
 
@@ -89,8 +73,7 @@ Suppose you want to find information about the + and - operations:
 ```
 #TODO:
 - Test on other implementations and operating systems (CCL, ECL, ABCL, CLISP, AllegroCL, LispWorks), to verify that it works.
-- Make debugging more user friendly.
-- `#F` reader macro (Ex: `#F.+[.+]` instead of `(fuck ".+[.+]")`
+- Make debugging more user friendly. Better documentation and some external functions to be called with `brain:function` or `brain:*variable*`
 
 This software is licensed under the MIT free software license.
 ====
diff --git a/interpreter.lisp b/interpreter.lisp
index 6dc0af7..cda089a 100644
--- a/interpreter.lisp
+++ b/interpreter.lisp
@@ -14,6 +14,8 @@
 ;;;; OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THIS BRAINFUCK SOFTWARE OR THE USE OR OTHER DEALINGS IN THIS 
 ;;;; BRAINFUCK SOFTWARE.
 (in-package :brain)
+(defconstant +close-bracket+ #\])
+(defconstant +open-bracket+ #\[)
 (defparameter *tape-size-default* 30000
   "The size of the tape, in bytes, used to store each byte")
 
@@ -49,6 +51,33 @@
   (setf *pointer* (pointer-default))
   (setf *output* ""))
 
+(defun char-list->string-aux (char-list string position)
+  (if (null (first char-list))
+      string
+      (char-list->string-aux (rest char-list)
+			     (progn (setf (char string position)
+					  (first char-list))
+				    string)
+			     (1+ position))))
+(defun char-list->string (char-list)
+  (char-list->string-aux char-list (make-string (length char-list)) 0))
+
+(defun shorthand-fuck-aux (stream list)
+  (let ((char (read-char stream nil nil)))
+    ;; TODO: Replace the #\Space, #\Newline, #\Tab with proper separations
+    (if (or (char-equal char #\Space)
+	    (char-equal char #\Newline)
+	    (char-equal char #\Tab)
+	    (null char))
+	(char-list->string (nreverse list))
+	(shorthand-fuck-aux stream (push char list)))))
+
+(defun shorthand-fuck (stream char subchar)
+  "This is a 'Reader Macro' that provides the #F notation"
+  (declare (ignore char subchar))
+  (list 'fuck (shorthand-fuck-aux stream nil)))
+(set-dispatch-macro-character #\# #\F #'shorthand-fuck)
+
 (defun wrap-pointer ()
   (cond ((= *pointer* *tape-size-default*) (setf *pointer* 0))
 		((= *pointer* -1) (setf *pointer* (1- *tape-size-default*)))))
@@ -88,7 +117,7 @@
 (defun goto-aux (current-position
 		 depth)
   (let ((this (elt *brainfuck* current-position)))
-    (if (char= #\[ this)
+    (if (char= +open-bracket+ this)
 	(if (= 1 depth)
 	    current-position
 	    (if (> depth 1)
@@ -96,7 +125,7 @@
 			  (1- depth))
 		(goto-aux (1- current-position)
 			  0)))
-	(if (char= #\] this)
+	(if (char= +close-bracket+ this)
 	    (goto-aux (1- current-position)
 		      (1+ depth))
 	    (goto-aux (1- current-position)
@@ -139,9 +168,9 @@
 
 (defun skip-loop-aux (position depth)
   (let ((this (char *brainfuck* position)))
-    (if (char= #\[ this)
+    (if (char= +open-bracket+ this)
 	(skip-loop-aux (1+ position) (1+ depth))
-	(if (char= #\] this)
+	(if (char= +close-bracket+ this)
 	    (if (= 1 depth)
 		(1+ position)
 		(skip-loop-aux (1+ position) (1- depth)))