RosettaCodeData/Task/Execute-Brain-/Ol/execute-brain-.ol

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)))))