更多 Brainf*ck – 回复:因子

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 次的时间。

阅读 11
0 条评论