2017-08-19 2 views
1

Ich habe den folgenden Brainfuck-Interpreter, der eine minimale Testsuite übergibt. Bis auf ein größeres Problem wie das Drucken der Fibonacci-Sequenz scheint es zu scheitern (der letzte Test in der Suite). Der Code von brainfuck fibonacci, den meine Interpretation nicht ausführt, stammt von http://esoteric.sange.fi/brainfuck/bf-source/prog/fibonacci.txt. Was stimmt nicht mit meiner Interpretation? Hier ist eine Geige: https://jsfiddle.net/rt017kpz/Brainfuck Interpreter falsches Verhalten

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

Haben Sie versucht, in einem Debugger durch den Code schrittweise, um herauszufinden, was es sein könnte? Und * wie * scheitert der Test? Stürzt es ab? Gib unerwartete Ergebnisse? Etwas anderes? –

+0

Danke für die Antwort, wenn Sie mein Code-Snippet ausführen, können Sie sehen, Fehler: erwartet ':' gleich '1, 1, 2, 3'. Wie mit einem Debugger, habe ich versucht, aber bf-Code ist so stark verschleiert. Ich hatte bisher kein Glück. Fibonacci bf-Code ist so groß. Leider ist es die einzige, die ich nicht richtig ausführen kann. –

+0

Ist Ihre ']' Implementierung korrekt? Ich würde erwarten, etwas wie 'if (data [ptr]! == 0) {while (code [codePtr]! ==' [') codePtr -; '(Ich denke, es ist wahrscheinlich in Ordnung. Du verwendest ein Array als Stapel.) –

Antwort

2

Ihre Implementierung von [ sucht nach dem ersten ] anstatt die passende ], die die zweite, dritte, vierte, usw. Symbol sein könnte ] . Sie müssen sie beim Scannen zählen. Der folgende Ausschnitt hat eine Implementierung von [, das dies tut, und der fib-Test funktioniert nun:

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>