81 lines
1.7 KiB
PHP
81 lines
1.7 KiB
PHP
<?php
|
|
|
|
namespace Automata;
|
|
|
|
use Automata\Storage\ProgramMemory;
|
|
use Automata\Storage\ToolMemory;
|
|
use Program\Block;
|
|
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) {
|
|
$this->executeBlock($block);
|
|
}
|
|
}
|
|
|
|
private function executeBlock(Block $block): void
|
|
{
|
|
/** @var Word[] $words */
|
|
$words = $block->words;
|
|
while ($word = array_shift($words)) {
|
|
$this->state->apply($word);
|
|
system('clear');
|
|
dump($this->state);
|
|
readline();
|
|
}
|
|
}
|
|
|
|
|
|
public function reset(): void
|
|
{
|
|
$this->activeProgram = null;
|
|
}
|
|
}
|