2017-08-19 71 views
1

我有以下Brainfuck解釋器通過最小測試套件。除了像打印斐波那契序列這樣的大問題似乎失敗(套件中的最後一個測試)。我解釋失誤執行的brainfuck斐波那契代碼是從http://esoteric.sange.fi/brainfuck/bf-source/prog/fibonacci.txt我的解釋有什麼問題? 這裏是一個小提琴:https://jsfiddle.net/rt017kpz/Brainfuck解釋器錯誤行爲

function brainLuck(code, input) { 
 
    // "Infinite" heap of memory initialized as 0 for bf to store program values 
 
    let data = new Proxy([], {get: (arr, i) => arr[i] ? arr[i] : 0 }) 
 
    let ptr = 0; 
 
    let inputPtr = 0; 
 
    let codePtr = 0; 
 
    let output = ''; 
 
    let loopStack = [] 
 

 
    const op = { 
 
    '+' :() => { 
 
     if (data[ptr] === 255) { data[ptr] = 0; } 
 
     else { data[ptr]++; } 
 
     codePtr++; 
 
    }, 
 
    '-' :() => { 
 
     if (data[ptr] === 0) { data[ptr] = 255; } 
 
     else { data[ptr]--; } 
 
     codePtr++; 
 
    }, 
 
    '.' :() => { 
 
     output += String.fromCharCode(data[ptr]); 
 
     codePtr++; 
 
    }, 
 
    ',' :() => { 
 
     data[ptr] = input.charCodeAt(inputPtr++); 
 
     codePtr++; 
 
    }, 
 
    '>' :() => { 
 
     ptr++; codePtr++; 
 
    }, 
 
    '<' :() => { 
 
     if (ptr > 0) { ptr--; } 
 
     codePtr++; 
 
    }, 
 
    '[' :() => { 
 
     if (data[ptr] === 0) { 
 
     while(code[codePtr] !== ']') codePtr++; 
 
     } else { 
 
     loopStack.unshift(codePtr); 
 
     } 
 
     codePtr++ 
 
    }, 
 
    ']' :() => { 
 
     if (data[ptr] === 0) { loopStack.shift(); } 
 
     else { codePtr = loopStack[0] } 
 
     codePtr++ 
 
    } 
 
    } 
 

 
    while(codePtr < code.length) { 
 
    if(op[code[codePtr]]) op[code[codePtr]]() 
 
    else codePtr++ 
 
    } 
 
    return output; 
 
} 
 

 

 

 
////////// TESTS ////////////// 
 

 
it('handles `+` and `.` operants',() => { 
 
    expect(
 
    brainLuck('+++.') 
 
).to.equal(
 
    String.fromCharCode(3) 
 
) 
 
}) 
 

 
it('handles `-` operant and underflows from 0 to 255',() => { 
 
    expect(
 
    brainLuck('+++----.') 
 
).to.equal(
 
    String.fromCharCode(255) 
 
) 
 
}) 
 

 
it('handles `,` the input operand',() => { 
 
    expect(
 
    brainLuck(',.', 'A') 
 
).to.equal(
 
    'A' 
 
) 
 
}) 
 

 
it('handles input in conjuction with arithmetic',() => { 
 
    expect(
 
    brainLuck(',+.', 'A') 
 
).to.equal(
 
    'B' 
 
) 
 
}) 
 

 
it('handles looping (`[`, `]`) and shift (`<`, `>`) operants',() => { 
 
    expect(
 
    brainLuck(',>+++[<.>-]', 'A') 
 
).to.equal(
 
    'AAA' 
 
) 
 
}) 
 

 
it('only parses known symbols',() => { 
 
    expect(
 
    brainLuck(',nothing>++else+[<.>matters!-]', 'A') 
 
).to.equal(
 
    'AAA' 
 
) 
 
}) 
 

 
it('handles nested loops',() => { 
 
    expect(
 
    brainLuck(',>+++[->+++[<<.>>-]<]', 'A') 
 
).to.equal(
 
    'AAAAAAAAA' 
 
) 
 
}) 
 

 
it('can multiply two numbers',() => { 
 
    expect(
 
    brainLuck(',>,<[>[->+>+<<]>>[-<<+>>]<<<-]>>.', String.fromCharCode(8,9)) 
 
).to.equal(
 
    String.fromCharCode(72) 
 
) 
 
}) 
 

 
it('can print the fibonacci sequence',() => { 
 
    expect(
 
    brainLuck('++++>+>>>>++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++<<<<<<[>[>>>>>>+>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<[>++++++++++[-<-[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<[>>>+<<<-]>>[-]]<<]>>>[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<+>>[-]]<<<<<<<]>>>>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]++++++++++<[->-<]>++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<<[-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]') 
 
).to.equal(
 
    '1, 1, 2, 3' 
 
) 
 
}) 
 

 

 
mocha.run();
<html> 
 
<head> 
 
    <meta charset="utf-8"> 
 
    <title>Mocha Tests</title> 
 
    <link href="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.css" rel="stylesheet" /> 
 
</head> 
 
<body> 
 
    <div id="mocha"></div> 
 
    <script src="https://cdn.rawgit.com/Automattic/expect.js/0.3.1/index.js"></script> 
 
    <script src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script> 
 
    <script>mocha.setup('bdd')</script> 
 
</body> 
 
</html>

+0

您是否嘗試過通過代碼在調試器步進找出它可能是什麼? * *測試失敗了嗎?它會「崩潰」嗎?意想不到的結果?還有別的嗎? –

+0

感謝您的迴應,如果您運行我的代碼片段,您可以看到'錯誤:預期':',等於'1,1,2,3''。至於使用調試器進行調試,我已經嘗試過,但是bf代碼是如此嚴重混淆。到目前爲止我沒有運氣。斐波那契bf代碼非常大。不幸的是,這是我唯一知道的不能正確執行的人。 –

+0

你的']'實現是否正確?我希望看到像'if(data [ptr]!== 0){while(code [codePtr]!=='[')codePtr - ;'(我認爲可能沒關係)數組作爲堆棧)。 –

回答

2

你實現[搜索第一],而不是匹配],這可能是第二,第三,第四等]符號。掃描時需要對它們進行計數。下面的代碼片段有[的實現,這樣做,和FIB測試現在工作:

function brainLuck(code, input) { 
 
    // "Infinite" heap of memory initialized as 0 for bf to store program values 
 
    let data = new Proxy([], {get: (arr, i) => arr[i] ? arr[i] : 0 }) 
 
    let ptr = 0; 
 
    let inputPtr = 0; 
 
    let codePtr = 0; 
 
    let output = ''; 
 
    let loopStack = [] 
 

 
    const op = { 
 
    '+' :() => { 
 
     if (data[ptr] === 255) { data[ptr] = 0; } 
 
     else { data[ptr]++; } 
 
     codePtr++; 
 
    }, 
 
    '-' :() => { 
 
     if (data[ptr] === 0) { data[ptr] = 255; } 
 
     else { data[ptr]--; } 
 
     codePtr++; 
 
    }, 
 
    '.' :() => { 
 
     output += String.fromCharCode(data[ptr]); 
 
     codePtr++; 
 
    }, 
 
    ',' :() => { 
 
     data[ptr] = input.charCodeAt(inputPtr++); 
 
     codePtr++; 
 
    }, 
 
    '>' :() => { 
 
     ptr++; codePtr++; 
 
    }, 
 
    '<' :() => { 
 
     if (ptr > 0) { ptr--; } 
 
     codePtr++; 
 
    }, 
 
    '[' :() => { 
 
     if (data[ptr] === 0) { 
 
     let level = 0; 
 
     while(code[codePtr] !== ']' || level > 1) { 
 
      if (code[codePtr] === '[') 
 
       level += 1; 
 
      if (code[codePtr] === ']') 
 
       level -= 1; 
 
      codePtr++; 
 
     } 
 
     } else { 
 
     loopStack.unshift(codePtr); 
 
     } 
 
     codePtr++ 
 
    }, 
 
    ']' :() => { 
 
     if (data[ptr] === 0) { loopStack.shift(); } 
 
     else { codePtr = loopStack[0] } 
 
     codePtr++ 
 
    } 
 
    } 
 

 
    while(codePtr < code.length) { 
 
    if(op[code[codePtr]]) op[code[codePtr]]() 
 
    else codePtr++ 
 
    } 
 
    return output; 
 
} 
 

 

 

 
////////// TESTS ////////////// 
 

 
it('handles `+` and `.` operants',() => { 
 
    expect(
 
    brainLuck('+++.') 
 
).to.equal(
 
    String.fromCharCode(3) 
 
) 
 
}) 
 

 
it('handles `-` operant and underflows from 0 to 255',() => { 
 
    expect(
 
    brainLuck('+++----.') 
 
).to.equal(
 
    String.fromCharCode(255) 
 
) 
 
}) 
 

 
it('handles `,` the input operand',() => { 
 
    expect(
 
    brainLuck(',.', 'A') 
 
).to.equal(
 
    'A' 
 
) 
 
}) 
 

 
it('handles input in conjuction with arithmetic',() => { 
 
    expect(
 
    brainLuck(',+.', 'A') 
 
).to.equal(
 
    'B' 
 
) 
 
}) 
 

 
it('handles looping (`[`, `]`) and shift (`<`, `>`) operants',() => { 
 
    expect(
 
    brainLuck(',>+++[<.>-]', 'A') 
 
).to.equal(
 
    'AAA' 
 
) 
 
}) 
 

 
it('only parses known symbols',() => { 
 
    expect(
 
    brainLuck(',nothing>++else+[<.>matters!-]', 'A') 
 
).to.equal(
 
    'AAA' 
 
) 
 
}) 
 

 
it('handles nested loops',() => { 
 
    expect(
 
    brainLuck(',>+++[->+++[<<.>>-]<]', 'A') 
 
).to.equal(
 
    'AAAAAAAAA' 
 
) 
 
}) 
 

 
it('can multiply two numbers',() => { 
 
    expect(
 
    brainLuck(',>,<[>[->+>+<<]>>[-<<+>>]<<<-]>>.', String.fromCharCode(8,9)) 
 
).to.equal(
 
    String.fromCharCode(72) 
 
) 
 
}) 
 

 
it('can print the fibonacci sequence',() => { 
 
    expect(
 
    brainLuck('++++>+>>>>++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++<<<<<<[>[>>>>>>+>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<[>++++++++++[-<-[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<[>>>+<<<-]>>[-]]<<]>>>[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<+>>[-]]<<<<<<<]>>>>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]++++++++++<[->-<]>++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<<[-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]') 
 
).to.equal(
 
    '1, 1, 2, 3' 
 
) 
 
}) 
 

 

 
mocha.run();
<html> 
 
<head> 
 
    <meta charset="utf-8"> 
 
    <title>Mocha Tests</title> 
 
    <link href="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.css" rel="stylesheet" /> 
 
</head> 
 
<body> 
 
    <div id="mocha"></div> 
 
    <script src="https://cdn.rawgit.com/Automattic/expect.js/0.3.1/index.js"></script> 
 
    <script src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script> 
 
    <script>mocha.setup('bdd')</script> 
 
</body> 
 
</html>