Skip to content

Commit b32016e

Browse files
committed
Add Common Lisp solution for problem 8.5: Brainfuck Interpreter
upstream repository: https://github.com/ryukinix/lisp-scripts
1 parent 4e689ab commit b32016e

File tree

1 file changed

+151
-0
lines changed
  • 8 - Interpreter and Compilers/5 - Brainfuck Interpreter

1 file changed

+151
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
;; A Brainfuck Interpreter written in Common Lisp
2+
;; Author: Manoel Vilela
3+
;; Date: 10/07/2017 02:24:40
4+
;; upstream: https://github.com/ryukinix/lisp-scripts
5+
6+
;; constants
7+
(defparameter *max-operations* 100000)
8+
(defparameter *valid-operations* "<>+-.,[]")
9+
10+
;; global variables
11+
(defparameter *memory* (make-array 100000 :initial-element 0))
12+
(defparameter *source* (make-array 5000 :initial-element #\0))
13+
(defparameter *source-pointer* 0)
14+
(defparameter *source-pointer-end* 0)
15+
(defparameter *operations* 0)
16+
(defparameter *data-pointer* 0)
17+
(defparameter *open-loop-stack* nil)
18+
(defparameter *input* nil)
19+
(defparameter *input-pointer* 0)
20+
21+
;; == I/O primitives ==
22+
23+
(defun valid-operation-p (char)
24+
(not (null (position char *valid-operations*))))
25+
26+
(defun read-source (source-length)
27+
(let ((source-pointer 0))
28+
(loop repeat source-length
29+
for line = (read-line)
30+
do (loop for char across line
31+
when (valid-operation-p char)
32+
do (progn (setf (aref *source* source-pointer) char)
33+
(incf source-pointer))))
34+
(setf *source-pointer-end* source-pointer)))
35+
36+
(defun get-user-input (input-length)
37+
(setf *input* (subseq (read-line) 0 input-length)))
38+
39+
(defun print-source ()
40+
(loop for x from 0 below *source-pointer-end*
41+
collect (princ (aref *source* x))))
42+
43+
(defun read-input ()
44+
(prog1 (aref *input* *input-pointer*)
45+
(incf *input-pointer*)))
46+
47+
;; == BRAINFUCK OPERATORS ==
48+
49+
;; .
50+
(defun print-data ()
51+
(princ (code-char (aref *memory* *data-pointer*)))
52+
(incf *source-pointer*))
53+
54+
;; ,
55+
(defun read-data ()
56+
(setf (aref *memory* *data-pointer*)
57+
(char-code (read-input)))
58+
(incf *source-pointer*))
59+
60+
(defun closed-loop-p ()
61+
(eql (aref *source* *source-pointer*) #\]))
62+
63+
(defun opened-loop-p ()
64+
(eql (aref *source* *source-pointer*) #\[))
65+
66+
(defun goto-end-of-loop ()
67+
(let ((loops 0))
68+
(loop when (opened-loop-p)
69+
do (incf loops)
70+
when (closed-loop-p)
71+
do (decf loops)
72+
when (and (closed-loop-p)
73+
(= loops 0))
74+
return nil
75+
do (incf *source-pointer*))))
76+
77+
(defun goto-start-of-loop ()
78+
(setf *source-pointer* (pop *open-loop-stack*)))
79+
80+
;; [
81+
(defun open-loop ()
82+
(push *source-pointer* *open-loop-stack*)
83+
(if (plusp (aref *memory* *data-pointer*))
84+
(incf *source-pointer*)
85+
(goto-end-of-loop)))
86+
87+
;; ]
88+
(defun close-loop ()
89+
(if (plusp (aref *memory* *data-pointer*))
90+
(goto-start-of-loop)
91+
(progn (pop *open-loop-stack*)
92+
(incf *source-pointer*))))
93+
94+
;; >
95+
(defun increment-data-pointer ()
96+
(incf *data-pointer*)
97+
(incf *source-pointer*))
98+
99+
;; <
100+
(defun decrement-data-pointer ()
101+
(unless (= 0 *data-pointer*)
102+
(decf *data-pointer*))
103+
(incf *source-pointer*))
104+
105+
;; +
106+
(defun increment-data ()
107+
(if (= (aref *memory* *data-pointer*) 255)
108+
(setf (aref *memory* *data-pointer*) 0)
109+
(incf (aref *memory* *data-pointer*)))
110+
(incf *source-pointer*))
111+
112+
;; -
113+
(defun decrement-data ()
114+
(if (= (aref *memory* *data-pointer*) 0)
115+
(setf (aref *memory* *data-pointer*) 255)
116+
(decf (aref *memory* *data-pointer*)))
117+
(incf *source-pointer*))
118+
119+
120+
(defun execute-step ()
121+
(case (aref *source* *source-pointer*)
122+
(#\+ (increment-data))
123+
(#\- (decrement-data))
124+
(#\> (increment-data-pointer))
125+
(#\< (decrement-data-pointer))
126+
(#\. (print-data))
127+
(#\, (read-data))
128+
(#\[ (open-loop))
129+
(#\] (close-loop)))
130+
(incf *operations*))
131+
132+
;; == PARSING & EXECUTION ==
133+
(defun interpret-program ()
134+
(loop while (< *source-pointer* *source-pointer-end*)
135+
when (>= *operations* *max-operations*)
136+
return (format t "~%PROCESS TIME OUT. KILLED!!!")
137+
do (execute-step)))
138+
139+
(defun show-memory ()
140+
(loop for x across *memory*
141+
collect x
142+
while (> x 0)))
143+
144+
(defun main ()
145+
(let ((input-length (read))
146+
(source-length (read)))
147+
(get-user-input input-length)
148+
(read-source source-length)
149+
(interpret-program)))
150+
151+
(main)

0 commit comments

Comments
 (0)