87 lines
1.9 KiB
PHP
87 lines
1.9 KiB
PHP
<?php
|
|
|
|
namespace Automata;
|
|
|
|
use Automata\Storage\ProgramMemory;
|
|
use Automata\Storage\ToolMemory;
|
|
use Program\Program;
|
|
use Program\Word;
|
|
use RuntimeException;
|
|
use SplStack;
|
|
|
|
/*
|
|
* executing a program:
|
|
* - load parts program
|
|
* - execute line by line
|
|
* - load sub program
|
|
* - execute lines from subprogram
|
|
* - back to parts program
|
|
*/
|
|
class Machine
|
|
{
|
|
public State $state;
|
|
public ToolMemory $toolMemory;
|
|
public ProgramMemory $subProgramMemory;
|
|
public ProgramMemory $partProgramMemory;
|
|
/** @var SplStack|Program[] */
|
|
private SplStack $programStack;
|
|
private ?Program $activeProgram = null;
|
|
private Definitions $definitions;
|
|
|
|
|
|
public function __construct()
|
|
{
|
|
$this->state = new State();
|
|
$this->definitions = new Definitions();
|
|
$this->toolMemory = new ToolMemory();
|
|
$this->subProgramMemory = new ProgramMemory();
|
|
$this->partProgramMemory = new ProgramMemory();
|
|
$this->programStack = new SplStack();
|
|
}
|
|
|
|
|
|
public function loadProgram(int $N): void
|
|
{
|
|
$this->programStack = new SplStack();
|
|
$program = $this->partProgramMemory->read($N);
|
|
$this->programStack->push($program);
|
|
}
|
|
|
|
|
|
public function start(): void
|
|
{
|
|
$this->activeProgram = $this->programStack->pop();
|
|
if (is_null($this->activeProgram)) {
|
|
throw new RuntimeException('No program loaded');
|
|
}
|
|
foreach ($this->activeProgram as $block) {
|
|
/** @var Word[] $words */
|
|
$words = $block->words;
|
|
while ($word = array_shift($words)) {
|
|
if ('G22' === $word->toString()) {
|
|
$identifier = array_shift($words);
|
|
if ($identifier->register !== 'X') {
|
|
throw new RuntimeException('Expected X9xxx after G22');
|
|
}
|
|
$subProgram = $this->subProgramMemory->read($identifier->value);
|
|
$this->programStack->push($subProgram);
|
|
system('clear');
|
|
dump($subProgram);
|
|
readline();
|
|
continue;
|
|
}
|
|
$this->state->apply($word);
|
|
system('clear');
|
|
dump($this->state);
|
|
readline();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public function reset(): void
|
|
{
|
|
$this->activeProgram = null;
|
|
}
|
|
}
|