Advertisement
Tooster

brainfuck interpreter racket

Mar 21st, 2018
384
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 4.83 KB | None | 0 0
  1. #lang racket
  2.  
  3. (define (make-state mem ptr flag register) (list mem ptr flag register))
  4. (define (mem-gen n) (build-list n (lambda (x) 0)))
  5. (define (get-mem state) (first state))
  6. (define (get-ptr state) (second state))
  7. (define (get-flag state) (third state)) ;; 1 = if(false) mode 0 = normal execution -1 = jumpto testwhile (backtrace)
  8. (define (get-register state) (fourth state))
  9. (define (mem-write mem ix val) (if [= ix 0] (list* val (cdr mem)) (list* (car mem) (mem-write (cdr mem) (sub1 ix) val))))
  10. (define (mem-read mem ix) (if [= ix 0] (car mem) (mem-read (cdr mem) (sub1 ix))))
  11. (define (opchar op) (cond [(eq? op '<) "<"] [(eq? op '>) ">"] [(eq? op '+) "+"] [(eq? op '-) "-"]
  12.                           [(eq? op 'r) "."] [(eq? op 'w) ","] [(eq? op 'if) "["] [(eq? op 'endif) "]"]
  13.                           [else "?"]))
  14.  
  15. (define (printstate state)
  16.   (printf " { P:~a F:~a R:~a } \tmemory:[~a]\n" (get-ptr state) (get-flag state) (get-register state) (get-mem state)))
  17. (define (op-primitive? op) (or (eq? op '>) (eq? op '<) (eq? op '+) (eq? op '-) (eq? op 'r) (eq? op 'w)))
  18.  
  19. (define (getop prog iptr)
  20.     (if [or (>= iptr (string-length prog))
  21.             (< iptr 0)]
  22.         null
  23.         (let ([instr (substring prog iptr (add1 iptr))])
  24.              (cond [(string=? instr ">") '>]
  25.                    [(string=? instr "<") '<]
  26.                    [(string=? instr "+") '+]
  27.                    [(string=? instr "-") '-]
  28.                    [(string=? instr ".") 'r]
  29.                    [(string=? instr ",") 'w]
  30.                    [(string=? instr "[") 'if]
  31.                    [(string=? instr "]") 'endif]
  32.                    [else 'comment]))))
  33.  
  34. (define (nextstate state op)
  35.   (let* ([mem (get-mem state)]
  36.          [ptr (get-ptr state)]
  37.          [F (get-flag state)]
  38.          [R (get-register state)]
  39.          [val (mem-read mem ptr)])
  40.         (cond [(and (op-primitive? op) (not (=(get-flag state) 0))) {cons state F}] ;; primitive and flag != 0 - return flag as shift for instr ptr
  41.               [(eq? op '+) {cons (make-state (mem-write mem ptr (add1 val)) ptr F R) 1}]
  42.               [(eq? op '-) {cons (make-state (mem-write mem ptr (sub1 val)) ptr F R) 1}]
  43.               [(eq? op '<) {cons (make-state mem (sub1 ptr) F R) 1}]
  44.               [(eq? op '>) {cons (make-state mem (add1 ptr) F R) 1}]
  45.               [(eq? op 'r) {display (integer->char (mem-read mem ptr))}{cons (make-state mem ptr F R) 1}]
  46.               [(eq? op 'w) {let* ([c (read-char)]
  47.                                   [c (if (eof-object? c) 0 (char->integer c))])
  48.                              (cons (make-state (mem-write mem ptr c) ptr F R) 1)}]
  49.               [(eq? op 'if)
  50.                           {cond [(= F 0) (if [= val 0]
  51.                                              (cons (make-state mem ptr 1 (add1 R)) 1) ;; skip mode - count parenthases
  52.                                              (cons state 1 ))] ;; eval mode - next character
  53.                                 [(= F 1) (cons (make-state mem ptr F (add1 R)) 1)]
  54.                                 [(= F -1) (if [= (add1 R) 0]
  55.                                               (cons (make-state mem ptr 0 (add1 R)) 0) ;; read same character without backtrace flag and don't move instruction ptr
  56.                                               (cons (make-state mem ptr F (add1 R)) F))]}] ;; read next character in backtrace mode
  57.               [(eq? op 'endif)
  58.                              {cond [(= F 0) (cons (make-state mem ptr -1 (sub1 R)) -1)] ;; set backtrace flag, fix prefix flag to -1 and move instruction ptr 1 back
  59.                                    [(= F 1) (if [= 0 (sub1 R)]
  60.                                                 (cons (make-state mem ptr 0 (sub1 R)) 1) ;; reset skip mode to normal mode
  61.                                                 (cons (make-state mem ptr F (sub1 R)) F))] ;; fix prefix sum and move further
  62.                                    [(= F -1) (cons (make-state mem ptr F (sub1 R)) F)] ;; last one shouldn't trigger with with proper code
  63.                                    }]
  64.               [else {cons state (if (>= F 0) 1 -1)}])))
  65.  
  66. (define (brainfuck-run prog state opptr verbose)  
  67.   (if [not (string? prog)]
  68.       (error "Program is not a string")
  69.       (let ([op (getop prog opptr)])
  70.         (cond [(null? op) state]
  71.               [(or (>= (get-ptr state) (length (get-mem state))) (< (get-ptr state) 0)) (error "Index array out of bounds.")]
  72.               [else (let* ([nxt (nextstate state op)]
  73.                            [opshift (cdr nxt)]
  74.                            [nxtst (car nxt)])
  75.                       (if verbose (printf "PENDING:~a" (opchar op)) null)
  76.                       (if verbose (printstate state) null)
  77.                       (brainfuck-run prog nxtst (+ opptr opshift) verbose))]))))
  78.  
  79. (define ($bf prog memory verbose) (brainfuck-run prog (make-state (mem-gen memory) 0 0 0) 0 verbose))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement