-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbrainfucl.lisp
More file actions
89 lines (73 loc) · 2.84 KB
/
brainfucl.lisp
File metadata and controls
89 lines (73 loc) · 2.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
;;;; brainfucl.lisp
(defpackage #:brainfucl
(:use #:cl))
(in-package #:brainfucl)
;;; "brainfucl" goes here. Hacks and glory await!
(defconstant +DEFAULT-DATA-POINTER+ (quote 0))
(defconstant +DEFAULT-CELL-ARRAY+ (quote (make-array 30000 :initial-element 0)))
(defconstant +DEFAULT-WHILE-STACK+ (quote nil))
(defparameter *data-pointer* (eval +DEFAULT-DATA-POINTER+))
(defparameter *cell-array* (eval +DEFAULT-CELL-ARRAY+))
(defparameter *while-stack* (eval +DEFAULT-WHILE-STACK+))
(defparameter *verbose* nil)
(defmacro current-cell ()
`(aref *cell-array* *data-pointer*))
(defun advance-pointer ()
(if (< *data-pointer* (length *cell-array*))
(incf *data-pointer*)
(error "No more cells!"))
(when *verbose* (format t "Advanced data pointer to ~D.~%" *data-pointer*)))
(defun back-pointer ()
(if (zerop *data-pointer*)
(error "No more cells!")
(decf *data-pointer*))
(when *verbose* (format t "Backed data pointer to ~D.~%" *data-pointer*)))
(defun increment-cell ()
(incf (current-cell))
(when *verbose*
(format t "Incremented cell ~D to value ~D.~%"
*data-pointer* (aref *cell-array* *data-pointer*))))
(defun decrement-cell ()
(decf (current-cell))
(when *verbose*
(format t "Decremented cell ~D to value ~D.~%"
*data-pointer* (aref *cell-array* *data-pointer*))))
(defun output-byte ()
(format t "~A" (code-char (current-cell))))
(defun input-byte ()
(setf (aref *cell-array* *data-pointer*) (read-byte *standard-input*)))
(defun restart-env ()
(setf *data-pointer* (eval +default-data-pointer+))
(setf *cell-array* (eval +default-cell-array+))
(setf *while-stack* (eval +default-while-stack+)))
(defun parse-bf (str)
(restart-env)
(do ((jump-pairs (get-jump-pairs str))
(string-pos 0 (1+ string-pos)))
((= string-pos (length str)))
(ecase (aref str string-pos)
(#\+ (increment-cell))
(#\- (decrement-cell))
(#\> (advance-pointer))
(#\< (back-pointer))
(#\. (output-byte))
(#\, (input-byte))
(#\Space nil)
(#\[ (when (zerop (current-cell))
(setf string-pos
(cdr (find string-pos jump-pairs :key #'car)))))
(#\] (when (not (zerop (current-cell)))
(setf string-pos
(car (find string-pos jump-pairs :key #'cdr))))))))
(defun get-jump-pairs (string)
"Return list of pairs (STARTPOS . ENDPOS) of positions of matching brackets."
(do ((strlen (length string))
(string-pos 0 (1+ string-pos))
(stack nil)
(result nil))
((= string-pos strlen) (if (null stack)
result
(error "Unmatched brackets found in string!")))
(case (aref string string-pos)
(#\[ (push string-pos stack))
(#\] (push (cons (pop stack) string-pos) result)))))