16 年前作者在Factor中实现了Brainfuck 编程语言。最近受一问启发,思考了将 Brainfuck 编译为引用的当前过程,以及解释器的工作方式。
- 当前实现将 Brainfuck 程序扩展为等价的 Factor 形式并运行,如示例所示,会合并多个相同操作符为单个动作。
对于第一个问题,利用解析词可简单地构建一个 Brainfuck 的 Factor 词:
SYNTAX: BRAINFUCK: scan-new-word ";" parse-tokens concat '[ _ run-brainfuck ] ( -- ) define-declared ;
并定义了包含注释的“Hello, World”程序:
BRAINFUCK: hello +++++ +++ ! Set Cell #0 to 8 [ >++++ ! Add 4 to Cell #1; this will always set Cell #1 to 4 [ ! as the cell will be cleared by the loop >++ ! Add 4*2 to Cell #2 >+++ ! Add 4*3 to Cell #3 >+++ ! Add 4*3 to Cell #4 >+ ! Add 4 to Cell #5 <<<<- ! Decrement the loop counter in Cell #1 ] ! Loop till Cell #1 is zero >+ ! Add 1 to Cell #2 >+ ! Add 1 to Cell #3 >- ! Subtract 1 from Cell #4 >>+ ! Add 1 to Cell #6 [<] ! Move back to the first zero cell you find; this will ! be Cell #1 which was cleared by the previous loop <- ! Decrement the loop Counter in Cell #0 ] ! Loop till Cell #0 is zero >>. ! Cell #2 has value 72 which is 'H' >---. ! Subtract 3 from Cell #3 to get 101 which is 'e' +++++ ++..+++. ! Likewise for 'llo' from Cell #3 >>. ! Cell #5 is 32 for the space <-. ! Subtract 1 from Cell #4 for 87 to give a 'W' <. ! Cell #3 was set to 'o' from the end of 'Hello' +++.----- -.----- ---. ! Cell #3 for 'rl' and 'd' >>+. ! Add 1 to Cell #5 gives us an exclamation point >++. ! And finally a newline from Cell #6 ;
对于第二个问题,构建了一个简单的 Brainfuck 解释器:
: end-loop ( str i -- str j/f ) CHAR: ] swap pick index-from dup [ 1 + ] when ; : start-loop ( str i -- str j/f ) 1 - CHAR: [ swap pick last-index-from dup [ 1 + ] when ; : interpret-brainfuck-from ( str i brainfuck -- str next/f brainfuck ) 2over swap?nth [ 1 + ] 2dip { { CHAR: > [ 1 (>) ] } { CHAR: < [ 1 (<) ] } { CHAR: + [ 1 (+) ] } { CHAR: - [ 1 (-) ] } { CHAR:. [ (.) ] } { CHAR:, [ (,) ] } { CHAR: # [ (#) ] } { CHAR: [ [ get-memory zero? [ [ end-loop ] dip ] when ] } { CHAR: ] [ get-memory zero? [ [ start-loop ] dip ] unless ] } { f [ [ drop f ] dip ] } [ blank? [ "Invalid input" throw ] unless ] } case ; : interpret-brainfuck ( str -- ) 0 <brainfuck> [ interpret-brainfuck-from over ] loop 3drop ;
并进行了性能测试,将编译后的run-brainfuck宏、上述解释器版本与使用stream-copy的原生版本进行比较,在输出到空流时,编译版比解释版快约 2 倍,但都比原生版慢;在“Hello, World”示例中,编译版比解释版快约 7 倍。同时测试了编译所需时间约为调用 10000 次的时间。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。