45 lines
2.5 KiB
Plaintext
45 lines
2.5 KiB
Plaintext
(define (bf program stack-length)
|
|
(let ((program (string-append program "]")); end
|
|
(program-counter 0)
|
|
(stack (make-bytevector stack-length 0))
|
|
(stack-pointer 0))
|
|
(letrec ((skip (lambda (PC sp in)
|
|
(let loop ((pc PC) (sp sp) (in in))
|
|
(let ((ch (string-ref program pc))
|
|
(pc (+ pc 1)))
|
|
(case ch
|
|
(#\] (list pc sp in))
|
|
(#\[ (apply loop (skip pc sp in)))
|
|
(else
|
|
(loop pc sp in)))))))
|
|
(step (lambda (PC SP IN)
|
|
(let loop ((pc PC) (sp SP) (in IN))
|
|
(let ((ch (string-ref program pc))
|
|
(pc (+ pc 1)))
|
|
(case ch
|
|
(#\] (list (- PC 1) sp in)) ; the end
|
|
(#\[ (if (eq? (ref stack sp) 0)
|
|
(apply loop (skip pc sp in))
|
|
(apply loop (step pc sp in))))
|
|
(#\+ (set-ref! stack sp (mod (+ (ref stack sp) 257) 256))
|
|
(loop pc sp in))
|
|
(#\- (set-ref! stack sp (mod (+ (ref stack sp) 255) 256))
|
|
(loop pc sp in))
|
|
(#\> (loop pc (+ sp 1) in))
|
|
(#\< (loop pc (- sp 1) in))
|
|
(#\. (display (string (ref stack sp)))
|
|
(loop pc sp in))
|
|
(#\, (let this ((in in))
|
|
(cond
|
|
((pair? in)
|
|
(set-ref! stack sp (car in))
|
|
(loop pc sp (cdr in)))
|
|
((null? in)
|
|
(set-ref! stack sp 0)
|
|
(loop pc sp in))
|
|
(else
|
|
(this (force in))))))
|
|
(else ; skip any invalid character
|
|
(loop pc sp in))))))))
|
|
(step 0 0 (port->bytestream stdin)))))
|