(defmacro whitespace-print-string (str) (cons 'progn (prepend-whitespace (iter (for c in-string str) (appending `((push ,(char-code c)) (print-char))))))) (defmacro whitespace-cond (&rest cases) "Like COND in Lisp, but uses the 0 value as T." (let ((end (gensym "END")) (case-labels (mapcar (lambda (x) (declare (ignore x)) (list (gensym) (gensym))) cases))) (cons 'progn (append (iter (for label in case-labels) (for (test body) in cases) (appending (append test (prepend-whitespace `((jz ,(first label)) (jmp ,(second label)) (mark ,(first label)))) body (prepend-whitespace `((jmp ,end) (mark ,(second label))))))) (prepend-whitespace `((mark ,end))))))) ;;; The classic FizzBuzz problem (with-open-file (s "/tmp/fizzbuzz.ws" :direction :output :if-exists :supersede) (whitespace (s) (for 1 100 (cond (((dup) (push 15) (mod)) ((print-string "FizzBuzz"))) (((dup) (push 3) (mod)) ((print-string "Fizz"))) (((dup) (push 5) (mod)) ((print-string "Buzz"))) (((push 0)) ((dup) (print-number)))) (push 10) (print-char)) (quit)))