philips-cnc6600-interpreter/src/Automata/Machine.php

75 lines
1.7 KiB
PHP

<?php
namespace Automata;
use Automata\Storage\ProgramMemory;
use Automata\Storage\ToolMemory;
use Program\Program;
use Program\Word;
use RuntimeException;
use SplStack;
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) {
// Do we apply a block or a word?
// Answer: depends! Some commands need
// more information from other words.
// TODO: Interpret commands such as preparation of a work cycle
$words = array_map(fn(Word $w) => $w->toString(), $block->words);
$words = implode("\t", $words);
$words = "N{$block->N}\t$words";
foreach ($block->words as $word) {
$this->state->apply($word);
system('clear');
print("\n $words\n\n");
dump($this->state);
readline();
}
}
}
public function reset(): void
{
$this->activeProgram = null;
}
}