Skip to content

Instantly share code, notes, and snippets.

@SerafimArts
Created October 10, 2019 14:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SerafimArts/ce7e0ca28b325e4c8794aede4ffd8a74 to your computer and use it in GitHub Desktop.
Save SerafimArts/ce7e0ca28b325e4c8794aede4ffd8a74 to your computer and use it in GitHub Desktop.
<?php
/**
* Class ExampleVm
*/
class ExampleVm
{
public const OP_ALLOC = 0x00;
public const OP_ADD = 0x01;
public const OP_GOTO = 0x02;
public const OP_ASSERT = 0x03;
public const OP_ASSERT_LTE = 0x04;
public const OP_INC = 0x05;
public const OP_ECHO = 0x06;
public array $symbols = [];
public function run(array $program): void
{
for ($state = 0, $len = \count($program); $state < $len; ++$state) {
[$code, $args] = $program[$state];
switch ($code) {
case self::OP_ALLOC:
$this->symbols[$args[0]] = $args[1];
break;
case self::OP_INC:
++$this->symbols[$args[0]];
break;
case self::OP_ADD:
if (\is_array($this->symbols[$args[0]])) {
$this->symbols[$args[0]][] = $this->symbols[$args[1]];
break;
}
throw new \RuntimeException('Bad type');
case self::OP_GOTO:
$state = ($args[0] - 1);
break;
case self::OP_ASSERT:
if (! $this->symbols[$args[0]]) {
$state = $args[1];
}
break;
case self::OP_ASSERT_LTE:
if ($this->symbols[$args[0]] > $args[1]) {
$state = $args[1];
}
break;
case self::OP_ECHO:
echo $this->symbols[$args[0]];
break;
}
}
}
}
<?php
$vm = new ExampleVm();
$before = \microtime(true);
$vm->run([
0 => [ExampleVm::OP_ALLOC, ['a', []]],
1 => [ExampleVm::OP_ALLOC, ['i', 0]],
2 => [ExampleVm::OP_ASSERT_LTE, ['i', 1000, 99]],
3 => [ExampleVm::OP_ADD, ['a', 'i']],
4 => [ExampleVm::OP_INC, ['i']],
5 => [ExampleVm::OP_GOTO, [2]],
6 => [ExampleVm::OP_ECHO, ['i']],
]);
echo number_format(\microtime(true) - $before, 6) . 's';
// 0.000354s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment