2024-12-17 15:42:06 -05:00
|
|
|
(load "utils.lisp")
|
|
|
|
|
2024-12-17 18:38:09 -05:00
|
|
|
(defmacro incmodf (place mod &optional (delta 1))
|
|
|
|
`(setf ,place (mod (+ ,place ,delta) ,mod)))
|
|
|
|
|
|
|
|
; TODO: ooo could totally gen from sym (e.g. '++-[]>)
|
|
|
|
; then i'd need some sort of var syntax ugh
|
|
|
|
(defpattern cmd (op val)
|
|
|
|
`(list ',op ,val))
|
|
|
|
|
|
|
|
; mandelbrot is about 5kb shorter with this :P
|
2024-12-18 01:01:45 -05:00
|
|
|
; zeroing-add gets us more
|
2024-12-17 18:38:09 -05:00
|
|
|
(defun optimize-loop (ins)
|
|
|
|
(match ins
|
|
|
|
((list (cmd inc _)) '(setf cell 0))
|
|
|
|
((guard
|
|
|
|
(list (cmd inc -1)
|
|
|
|
(cmd minc rmove)
|
|
|
|
(cmd inc 1)
|
|
|
|
(cmd minc lmove))
|
|
|
|
(= lmove (- rmove))) ; [->{n}+<{n}]
|
|
|
|
`(zeroing-add ,rmove))
|
|
|
|
; maybe warn here?
|
|
|
|
((list) '(unless (zerop cell) (loop)))
|
|
|
|
(_ nil)))
|
|
|
|
|
2024-12-17 15:42:06 -05:00
|
|
|
(defun comp-part (&optional (port *standard-input*))
|
|
|
|
(begin
|
2024-12-17 16:27:04 -05:00
|
|
|
(= out nil)
|
|
|
|
(= op 'inc)
|
|
|
|
(= val 0)
|
|
|
|
(=f put (&optional (next 'inc))
|
|
|
|
(unless (zerop val) (push (list op val) out))
|
|
|
|
(setf op next)
|
|
|
|
(setf val 0))
|
|
|
|
|
|
|
|
(loop for c = (read-char port nil nil)
|
2024-12-17 15:42:06 -05:00
|
|
|
while (and c (not (eql c #\])))
|
|
|
|
when (in c #\+ #\- #\> #\< #\. #\, #\[)
|
2024-12-17 16:27:04 -05:00
|
|
|
do (ecase c
|
|
|
|
((#\+ #\-)
|
|
|
|
(unless (eq op 'inc) (put 'inc))
|
|
|
|
(incf val (if (eql c #\+) 1 -1)))
|
|
|
|
|
|
|
|
((#\> #\<)
|
|
|
|
(unless (eq op 'minc) (put 'minc))
|
|
|
|
(incf val (if (eql c #\>) 1 -1)))
|
|
|
|
|
|
|
|
(#\. (put) (push '(put-byte) out))
|
|
|
|
(#\, (put) (push '(get-byte) out))
|
2024-12-17 18:38:09 -05:00
|
|
|
(#\[ (put)
|
|
|
|
(let1 inner (comp-part port)
|
|
|
|
(push (or (optimize-loop inner)
|
2024-12-18 01:01:45 -05:00
|
|
|
`(loop until (zerop cell)
|
|
|
|
do (progn ,@inner)))
|
2024-12-17 18:38:09 -05:00
|
|
|
out))))
|
2024-12-18 14:01:36 -05:00
|
|
|
;; WE NEED TO PUT BECAUSE LOOPS IDOIT!
|
|
|
|
finally (put)
|
2024-12-17 18:38:09 -05:00
|
|
|
finally (return (nreverse out)))))
|
2024-12-17 15:42:06 -05:00
|
|
|
|
2024-12-18 01:01:45 -05:00
|
|
|
(defparameter mem-size 32768)
|
|
|
|
|
2024-12-17 15:42:06 -05:00
|
|
|
(defun comp (&optional (port *standard-input*))
|
2024-12-17 16:27:04 -05:00
|
|
|
(eval
|
|
|
|
`(lambda (&key (in *standard-input*) (out *standard-output*))
|
2024-12-17 18:38:09 -05:00
|
|
|
(declare (optimize (speed 3) (safety 0)))
|
2024-12-17 16:27:04 -05:00
|
|
|
(begin
|
2024-12-18 01:01:45 -05:00
|
|
|
(= mem (make-array ,mem-size :element-type '(unsigned-byte 8)))
|
2024-12-17 16:27:04 -05:00
|
|
|
(= mp 0)
|
2024-12-18 14:01:36 -05:00
|
|
|
(declare (type (mod ,mem-size) mp))
|
|
|
|
|
2024-12-17 16:27:04 -05:00
|
|
|
(=sm cell (aref mem mp))
|
|
|
|
|
2024-12-18 01:01:45 -05:00
|
|
|
(=f inc (n) (incmodf cell 256 n))
|
|
|
|
(=f minc (n) (incmodf mp ,mem-size n))
|
2024-12-17 16:27:04 -05:00
|
|
|
|
2024-12-17 18:38:09 -05:00
|
|
|
; TODO: fix
|
2024-12-17 16:27:04 -05:00
|
|
|
(=f get-byte () (setf cell (mod (char-code (read-char in nil #\null)) 256)))
|
|
|
|
(=f put-byte () (write-char (code-char cell) out))
|
|
|
|
|
2024-12-17 18:38:09 -05:00
|
|
|
(=f zeroing-add (rmove)
|
2024-12-18 01:01:45 -05:00
|
|
|
(incmodf (aref mem (mod (+ mp rmove) ,mem-size)) 256 cell)
|
2024-12-17 18:38:09 -05:00
|
|
|
(setf cell 0))
|
|
|
|
|
2024-12-17 16:27:04 -05:00
|
|
|
,@(comp-part port)
|
2024-12-17 18:38:09 -05:00
|
|
|
|
2024-12-17 16:27:04 -05:00
|
|
|
t))))
|
2024-12-17 18:38:09 -05:00
|
|
|
|
|
|
|
(defun main ()
|
2024-12-20 02:28:06 -05:00
|
|
|
(funcall
|
|
|
|
(aif (second *posix-argv*)
|
|
|
|
(with-input-from-file (f it) (comp f))
|
|
|
|
(comp))))
|