<commit_before><?php

namespace igorw\brainfuck;

use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;

/** @api */
function execute($code, LoggerInterface $logger = null)
{
    $vm = new Machine($code, $logger);
    return $vm->execute();
}

// in order to allow consuming single chars,
// make sure to run with:
//   system("stty -icanon");
//
// source: http://stackoverflow.com/a/3684565/289985
class Machine
{
    public $code;
    public $ip = 0;

    public $tape;
    public $p = 0;

    public $logger;

    function __construct($code, LoggerInterface $logger = null)
    {
        $this->code = str_split($code);
        $this->tape = array_fill(0, 30000, 0);
        $this->logger = $logger ?: new NullLogger();
    }

    function execute()
    {
        $this->logger->info('init', ['p' => $this->p]);

        while (isset($this->code[$this->ip])) {
            $op = $this->code[$this->ip++];

            switch ($op) {
                case '>':
                    $this->p++;
                    $this->logger->info('right', ['p' => $this->p]);
                    break;
                case '<':
                    $this->p--;
                    $this->logger->info('left', ['p' => $this->p]);
                    break;
                case '+':
                    $this->tape[$this->p]++;
                    $this->logger->info('inc', ['p' => $this->p]);
                    break;
                case '-':
                    $this->tape[$this->p]--;
                    $this->logger->info('dec', ['p' => $this->p]);
                    break;
                case '.':
                    $char = chr($this->tape[$this->p]);
                    echo $char;
                    $this->logger->info('input', ['p' => $this->p, 'char' => $char]);
                    break;
                case ',':
                    $char = fread(STDIN, 1);
                    $this->tape[$this->p] = ($char === "\x04") ? 0 : ord($char);
                    $this->logger->info('output', ['p' => $this->p, 'char' => ($char === "\x04") ? 'EOF' : $char]);
                    break;
                case '[':
                    if (!$this->tape[$this->p])
                        while ($this->code[$this->ip++] !== ']')
                            ;
                    $this->logger->info('while', ['p' => $this->p]);
                    break;
                case ']':
                    while ($this->code[--$this->ip] !== '[')
                        ;
                    $this->logger->info('endwhile', ['p' => $this->p]);
                    break;
                case ' ':
                case "\n":
                    // noop
                    break;
                default:
                    throw new \RuntimeException(sprintf('Invalid instruction %s', $op));
                    break;
            }
        }
    }
}
<commit_msg>be more permissive, simply ignore unknown instructions<commit_after><?php

namespace igorw\brainfuck;

use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;

/** @api */
function execute($code, LoggerInterface $logger = null)
{
    $vm = new Machine($code, $logger);
    return $vm->execute();
}

// in order to allow consuming single chars,
// make sure to run with:
//   system("stty -icanon");
//
// source: http://stackoverflow.com/a/3684565/289985
class Machine
{
    public $code;
    public $ip = 0;

    public $tape;
    public $p = 0;

    public $logger;

    function __construct($code, LoggerInterface $logger = null)
    {
        $this->code = str_split($code);
        $this->tape = array_fill(0, 30000, 0);
        $this->logger = $logger ?: new NullLogger();
    }

    function execute()
    {
        $this->logger->info('init', ['p' => $this->p]);

        while (isset($this->code[$this->ip])) {
            $op = $this->code[$this->ip++];

            switch ($op) {
                case '>':
                    $this->p++;
                    $this->logger->info('right', ['p' => $this->p]);
                    break;
                case '<':
                    $this->p--;
                    $this->logger->info('left', ['p' => $this->p]);
                    break;
                case '+':
                    $this->tape[$this->p]++;
                    $this->logger->info('inc', ['p' => $this->p]);
                    break;
                case '-':
                    $this->tape[$this->p]--;
                    $this->logger->info('dec', ['p' => $this->p]);
                    break;
                case '.':
                    $char = chr($this->tape[$this->p]);
                    echo $char;
                    $this->logger->info('input', ['p' => $this->p, 'char' => $char]);
                    break;
                case ',':
                    $char = fread(STDIN, 1);
                    $this->tape[$this->p] = ($char === "\x04") ? 0 : ord($char);
                    $this->logger->info('output', ['p' => $this->p, 'char' => ($char === "\x04") ? 'EOF' : $char]);
                    break;
                case '[':
                    if (!$this->tape[$this->p])
                        while ($this->code[$this->ip++] !== ']')
                            ;
                    $this->logger->info('while', ['p' => $this->p]);
                    break;
                case ']':
                    while ($this->code[--$this->ip] !== '[')
                        ;
                    $this->logger->info('endwhile', ['p' => $this->p]);
                    break;
                default:
                    // noop
                    break;
            }
        }
    }
}

{'fraction_non_alphanumeric': 0.19243127454480544, 'fraction_numerical': 0.009996429846483398, 'mean_word_length': 1.2015717092337916, 'pattern_counts': {'":': 1, '<': 7, '<?xml version=': 0, '>': 129, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3037874', 'n_tokens_mistral': 1692, 'n_tokens_neox': 1554, 'n_words': 310}