#!/usr/bin/env racket
#lang racket/base
(define (brainfuck ptr memory c)
(if (eof-object? c)
memory
(case c
((#\>) (let ((ptr (+ ptr 1)))
(brainfuck ptr `(inc-ptr ,ptr ,memory) (read-char))))
((#\<) (brainfuck (- ptr 1) `(dec-ptr ,(- ptr 1) ,memory) (read-char)))
((#\+) (brainfuck ptr `(inc-val ,ptr ,memory) (read-char)))
((#\-) (brainfuck ptr `(dec-val ,ptr ,memory) (read-char)))
((#\.) (brainfuck ptr `(putchar ,ptr ,memory) (read-char)))
((#\,) (brainfuck ptr `(getchar ,ptr ,memory) (read-char)))
((#\[) (brainfuck ptr
`(do ((memory ,memory ,(brainfuck ptr 'memory (read-char))))
((zero? (list-ref memory (- (length memory) ,ptr 1))) memory))
(read-char)))
((#\]) memory)
(else (brainfuck ptr memory (read-char))))))
(define (compile file0 file1)
(with-input-from-file file0
(lambda ()
(with-output-to-file file1
(lambda ()
(for-each display
`("#!/usr/bin/env racket\n"
"#lang racket\n"
(require srfi/1)
"\n"
(define (inc-ptr k lst)
(let ((n (+ k 1)))
(if (> n (length lst))
(cons 0 lst)
lst)))
"\n"
(define (dec-ptr k lst)
lst)
"\n"
(define (inc-val k lst)
(let ((n (- (length lst) k 1)))
(let-values (((head tail) (split-at lst n)))
(let ((val (+ (car tail) 1)))
(append head (cons val (cdr tail)))))))
"\n"
(define (dec-val k lst)
(let ((n (- (length lst) k 1)))
(let-values (((head tail) (split-at lst n)))
(let ((val (- (car tail) 1)))
(append head (cons val (cdr tail)))))))
"\n"
(define (putchar k lst)
(let ((n (- (length lst) k 1)))
(display (integer->char (list-ref lst n)))
lst))
"\n"
(define (getchar k lst)
(let ((n (- (length lst) k 1)))
(let-values (((head tail) (split-at lst n)))
(append head (cons (char->integer (read-char)) (cdr tail))))))
"\n"
,(brainfuck 0 ''(0) (read-char)))
))))))
IyEvdXNyL2Jpbi9lbnYgcmFja2V0CiNsYW5nIHJhY2tldC9iYXNlCgooZGVmaW5lIChicmFpbmZ1Y2sgcHRyIG1lbW9yeSBjKQogIChpZiAoZW9mLW9iamVjdD8gYykKICAgICBtZW1vcnkKICAgICAoY2FzZSBjCiAgICAgICAoKCNcPikgKGxldCAoKHB0ciAoKyBwdHIgMSkpKQogICAgICAgICAgICAgICAgKGJyYWluZnVjayBwdHIgYChpbmMtcHRyICxwdHIgLG1lbW9yeSkgKHJlYWQtY2hhcikpKSkKICAgICAgICgoI1w8KSAoYnJhaW5mdWNrICgtIHB0ciAxKSBgKGRlYy1wdHIgLCgtIHB0ciAxKSAsbWVtb3J5KSAocmVhZC1jaGFyKSkpCiAgICAgICAoKCNcKykgKGJyYWluZnVjayBwdHIgYChpbmMtdmFsICxwdHIgLG1lbW9yeSkgKHJlYWQtY2hhcikpKQogICAgICAgKCgjXC0pIChicmFpbmZ1Y2sgcHRyIGAoZGVjLXZhbCAscHRyICxtZW1vcnkpIChyZWFkLWNoYXIpKSkKICAgICAgICgoI1wuKSAoYnJhaW5mdWNrIHB0ciBgKHB1dGNoYXIgLHB0ciAsbWVtb3J5KSAocmVhZC1jaGFyKSkpCiAgICAgICAoKCNcLCkgKGJyYWluZnVjayBwdHIgYChnZXRjaGFyICxwdHIgLG1lbW9yeSkgKHJlYWQtY2hhcikpKQogICAgICAgKCgjXFspIChicmFpbmZ1Y2sgcHRyCiAgICAgICAgICAgICAgICAgICAgICAgIGAoZG8gKChtZW1vcnkgLG1lbW9yeSAsKGJyYWluZnVjayBwdHIgJ21lbW9yeSAocmVhZC1jaGFyKSkpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAoKHplcm8/IChsaXN0LXJlZiBtZW1vcnkgKC0gKGxlbmd0aCBtZW1vcnkpICxwdHIgMSkpKSBtZW1vcnkpKQogICAgICAgICAgICAgICAgICAgICAgICAocmVhZC1jaGFyKSkpCiAgICAgICAoKCNcXSkgbWVtb3J5KQogICAgICAgKGVsc2UgKGJyYWluZnVjayBwdHIgbWVtb3J5IChyZWFkLWNoYXIpKSkpKSkKCihkZWZpbmUgKGNvbXBpbGUgZmlsZTAgZmlsZTEpCiAgKHdpdGgtaW5wdXQtZnJvbS1maWxlIGZpbGUwCiAgICAobGFtYmRhICgpCiAgICAgICh3aXRoLW91dHB1dC10by1maWxlIGZpbGUxCiAgICAgICAgKGxhbWJkYSAoKQogICAgICAgICAgKGZvci1lYWNoIGRpc3BsYXkKICAgICAgICAgICAgICAgICAgIGAoIiMhL3Vzci9iaW4vZW52IHJhY2tldFxuIgogICAgICAgICAgICAgICAgICAgICAiI2xhbmcgcmFja2V0XG4iCiAgICAgICAgICAgICAgICAgICAgIChyZXF1aXJlIHNyZmkvMSkKICAgICAgICAgICAgICAgICAgICAgIlxuIgogICAgICAgICAgICAgICAgICAgICAoZGVmaW5lIChpbmMtcHRyIGsgbHN0KQogICAgICAgICAgICAgICAgICAgICAgIChsZXQgKChuICgrIGsgMSkpKQogICAgICAgICAgICAgICAgICAgICAgICAgKGlmICg+IG4gKGxlbmd0aCBsc3QpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNvbnMgMCBsc3QpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsc3QpKSkKICAgICAgICAgICAgICAgICAgICAgIlxuIgogICAgICAgICAgICAgICAgICAgICAoZGVmaW5lIChkZWMtcHRyIGsgbHN0KQogICAgICAgICAgICAgICAgICAgICAgIGxzdCkKICAgICAgICAgICAgICAgICAgICAgIlxuIgogICAgICAgICAgICAgICAgICAgICAoZGVmaW5lIChpbmMtdmFsIGsgbHN0KQogICAgICAgICAgICAgICAgICAgICAgIChsZXQgKChuICgtIChsZW5ndGggbHN0KSBrIDEpKSkKICAgICAgICAgICAgICAgICAgICAgICAgIChsZXQtdmFsdWVzICgoKGhlYWQgdGFpbCkgKHNwbGl0LWF0IGxzdCBuKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgIChsZXQgKCh2YWwgKCsgKGNhciB0YWlsKSAxKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGFwcGVuZCBoZWFkIChjb25zIHZhbCAoY2RyIHRhaWwpKSkpKSkpCiAgICAgICAgICAgICAgICAgICAgICJcbiIKICAgICAgICAgICAgICAgICAgICAgKGRlZmluZSAoZGVjLXZhbCBrIGxzdCkKICAgICAgICAgICAgICAgICAgICAgICAobGV0ICgobiAoLSAobGVuZ3RoIGxzdCkgayAxKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAobGV0LXZhbHVlcyAoKChoZWFkIHRhaWwpIChzcGxpdC1hdCBsc3QgbikpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAobGV0ICgodmFsICgtIChjYXIgdGFpbCkgMSkpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIChhcHBlbmQgaGVhZCAoY29ucyB2YWwgKGNkciB0YWlsKSkpKSkpKQogICAgICAgICAgICAgICAgICAgICAiXG4iCiAgICAgICAgICAgICAgICAgICAgIChkZWZpbmUgKHB1dGNoYXIgayBsc3QpCiAgICAgICAgICAgICAgICAgICAgICAgKGxldCAoKG4gKC0gKGxlbmd0aCBsc3QpIGsgMSkpKQogICAgICAgICAgICAgICAgICAgICAgICAgKGRpc3BsYXkgKGludGVnZXItPmNoYXIgKGxpc3QtcmVmIGxzdCBuKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICBsc3QpKQogICAgICAgICAgICAgICAgICAgICAiXG4iCiAgICAgICAgICAgICAgICAgICAgIChkZWZpbmUgKGdldGNoYXIgayBsc3QpCiAgICAgICAgICAgICAgICAgICAgICAgKGxldCAoKG4gKC0gKGxlbmd0aCBsc3QpIGsgMSkpKQogICAgICAgICAgICAgICAgICAgICAgICAgKGxldC12YWx1ZXMgKCgoaGVhZCB0YWlsKSAoc3BsaXQtYXQgbHN0IG4pKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgKGFwcGVuZCBoZWFkIChjb25zIChjaGFyLT5pbnRlZ2VyIChyZWFkLWNoYXIpKSAoY2RyIHRhaWwpKSkpKSkKICAgICAgICAgICAgICAgICAgICAgIlxuIgogICAgICAgICAgICAgICAgICAgICAsKGJyYWluZnVjayAwICcnKDApIChyZWFkLWNoYXIpKSkKICAgICAgICAgICAgICAgICAgICkpKSkpKQ==