philips-cnc6600-interpreter/src/Automata/Machine.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;
}
}