如何解决为什么这个断言对我的基于 Scheme 的 Brainfuck 解释器失败了?
我正在用 Scheme (Chez Scheme) 编写一个 Brainfuck 解释器。似乎无论我使用哪个 Brainfuck 程序,它都不起作用,而且我不知道为什么。我想我会用谢尔宾斯基三角形的代码(来自 here,测试过 here)和一个 Hello World 来试试:
(define hello-world "+[-[<<[+[--->]-[<<<]]]>>>-]>-.---.>..>.<<<<-.<+.>>>>>.>.<<.<-.")
(define sierpinski "++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[-<<<[->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<]>.>+[>>]>+]")
(entry-point hello-world 100)
失败如下:
|#\<
|(elem-at
-1
(255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))
Exception: Failed assertion (>= i 0) at line 7,char 10 of interpret.scm
当我使用 elem-at
时,索引参数始终是指令指针或数据指针。那么奇怪的是,这里的指针竟然小于 1。
(entry-point sierpinski 20)
失败如下:
|#\+
|(elem-at 20 (0 10 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 31 0))
|(elem-at 19 (10 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 31 0))
|(elem-at 18 (1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 31 0))
|(elem-at 17 (1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 31 0))
|(elem-at 16 (1 0 1 0 1 0 1 0 1 0 1 0 1 0 31 0))
|(elem-at 15 (0 1 0 1 0 1 0 1 0 1 0 1 0 31 0))
|(elem-at 14 (1 0 1 0 1 0 1 0 1 0 1 0 31 0))
|(elem-at 13 (0 1 0 1 0 1 0 1 0 1 0 31 0))
|(elem-at 12 (1 0 1 0 1 0 1 0 1 0 31 0))
|(elem-at 11 (0 1 0 1 0 1 0 1 0 31 0))
|(elem-at 10 (1 0 1 0 1 0 1 0 31 0))
|(elem-at 9 (0 1 0 1 0 1 0 31 0))
|(elem-at 8 (1 0 1 0 1 0 31 0))
|(elem-at 7 (0 1 0 1 0 31 0))
|(elem-at 6 (1 0 1 0 31 0))
|(elem-at 5 (0 1 0 31 0))
|(elem-at 4 (1 0 31 0))
|(elem-at 3 (0 31 0))
|(elem-at 2 (31 0))
|(elem-at 1 (0))
|(elem-at 0 ())
Exception in car: () is not a pair
同样,指针还有另一个问题,特别是 data-ptr
。这让我非常困惑。我的代码如下。有人知道我的翻译有什么问题吗?
(define (token-list chars)
(filter
(lambda (c) (memq c (list #\> #\< #\+ #\- #\. #\,#\[ #\])))
(string->list chars)))
(trace-define (elem-at i lst)
(assert (>= i 0))
(if (zero? i) (car lst)
(elem-at (sub1 i) (cdr lst))))
(define (change-byte! i cells modifier)
(if (zero? i)
(set-car! cells (modifier (car cells)))
(change-byte! (sub1 i) (cdr cells) modifier)))
(define (print-status! cells instr instr-ptr data-ptr)
(format #t "Cells = ~a,instr = ~a,instr ptr = ~a,data ptr = ~a\n"
cells instr instr-ptr data-ptr))
(define (update-data-ptr instr data-ptr)
(case instr
(#\> (add1 data-ptr))
(#\< (sub1 data-ptr))
(else data-ptr)))
(define (ptr-after-jump program instr-ptr mover end)
(if (eq? (elem-at instr-ptr program) end)
instr-ptr
(ptr-after-jump program (mover instr-ptr) mover end)))
(define (update-instr-ptr instr-ptr instr program cell)
(add1
(cond
((and (eq? instr #\[) (zero? cell))
(ptr-after-jump program instr-ptr add1 #\]))
((and (eq? instr #\]) (not (zero? cell)))
(ptr-after-jump program instr-ptr sub1 #\[))
(else instr-ptr))))
(define (interpret program instr-ptr data-ptr cells)
(when (not (= instr-ptr (length program)))
(let ((instr (elem-at instr-ptr program)))
(begin
(print-status! cells instr instr-ptr data-ptr)
(case instr
(#\+ (change-byte! data-ptr cells
(if (= (elem-at data-ptr cells) 255)
(lambda (_) 0) add1)))
(#\- (change-byte! data-ptr cells
(if (zero? (elem-at data-ptr cells))
(lambda (_) 255) sub1)))
(#\. (display (integer->char (elem-at data-ptr cells))))
(#\,(change-byte! data-ptr cells (lambda (_) (char->integer (read-char))))))
(interpret
program
(update-instr-ptr instr-ptr instr program (elem-at data-ptr cells)); the problem may be around here
(update-data-ptr instr data-ptr)
cells)))))
(define (init-cells length buf)
(if (zero? length) buf
(init-cells (sub1 length) (cons 0 buf))))
(define (entry-point code tape-length)
(interpret
(token-list code)
0 0; (floor (/ tape-length 2))
(init-cells tape-length '())))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。