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