diff options
| author | nsfisis <nsfisis@gmail.com> | 2024-07-13 14:10:40 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2024-07-13 14:10:40 +0900 |
| commit | f26f497131923886889deb4b843b179518888b1f (patch) | |
| tree | 10ff8467135865d4aadb6bf4d3978dd1d011ed1a | |
| parent | 1f4170811730477e9cd7d9620608c4ab619bdefc (diff) | |
| download | php-waddiwasi-f26f497131923886889deb4b843b179518888b1f.tar.gz php-waddiwasi-f26f497131923886889deb4b843b179518888b1f.tar.zst php-waddiwasi-f26f497131923886889deb4b843b179518888b1f.zip | |
feat: add examples/hello-world
| -rw-r--r-- | README.md | 8 | ||||
| -rw-r--r-- | composer.json | 1 | ||||
| -rw-r--r-- | examples/hello-world/index.php | 35 | ||||
| -rw-r--r-- | phpstan.neon | 1 | ||||
| -rw-r--r-- | src/Stream/BlobStream.php | 95 | ||||
| -rw-r--r-- | src/Stream/StreamInterface.php | 8 |
6 files changed, 144 insertions, 4 deletions
@@ -8,6 +8,13 @@ It is partially compatible with the WebAssembly specification version 2.0. ## Examples +### Hello, World! + +``` +$ composer example:hello-world +``` + + ### PHP on Wasm The PHP runtime can be compiled to WebAssembly binary. This Wasm runtime can execute it. Currently, "Hello, World!" program works on the PHP runtime on the Wasm runtime. @@ -16,6 +23,7 @@ The PHP runtime can be compiled to WebAssembly binary. This Wasm runtime can exe $ composer example:php-on-wasm ``` + ### RubyVM on PHP on Wasm https://github.com/m3m0r7/rubyvm-on-php is a RubyVM written in pure PHP. diff --git a/composer.json b/composer.json index 4324026..d459092 100644 --- a/composer.json +++ b/composer.json @@ -33,6 +33,7 @@ ], "ecs": "ecs check", "ecsfix": "ecs --memory-limit=1G check --fix", + "example:hello-world": "@php examples/hello-world/index.php", "example:php-on-wasm": "@php -d memory_limit=256M -d opcache.enable_cli=on -d opcache.jit=on -d opcache.jit_buffer_size=1G examples/php-on-wasm/php-wasm.php", "example:rubyvm-on-php-on-wasm": "@php -d memory_limit=-1 -d opcache.enable_cli=on -d opcache.jit=on -d opcache.jit_buffer_size=2G examples/rubyvm-on-php-on-wasm/php-wasm.php", "lint": [ diff --git a/examples/hello-world/index.php b/examples/hello-world/index.php new file mode 100644 index 0000000..9b0b1bd --- /dev/null +++ b/examples/hello-world/index.php @@ -0,0 +1,35 @@ +<?php + +declare(strict_types=1); + +require_once __DIR__ . '/../../vendor/autoload.php'; + +use Nsfisis\Waddiwasi\Stream\BlobStream; +use Nsfisis\Waddiwasi\WebAssembly\BinaryFormat\Decoder; +use Nsfisis\Waddiwasi\WebAssembly\Execution\Extern; +use Nsfisis\Waddiwasi\WebAssembly\Execution\FuncInst; +use Nsfisis\Waddiwasi\WebAssembly\Execution\Linker; +use Nsfisis\Waddiwasi\WebAssembly\Execution\Runtime; +use Nsfisis\Waddiwasi\WebAssembly\Execution\Store; +use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\FuncType; +use Nsfisis\Waddiwasi\WebAssembly\Structure\Types\ValType; + +$wasmBinary = ("" + . "\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x08\x02\x60\x00\x00\x60\x01" + . "\x7f\x00\x02\x09\x01\x00\x04\x70\x75\x74\x63\x00\x01\x03\x02\x01" + . "\x00\x07\x08\x01\x04\x6d\x61\x69\x6e\x00\x01\x0a\x46\x01\x44\x00" + . "\x41\xc8\x00\x10\x00\x41\xe5\x00\x10\x00\x41\xec\x00\x10\x00\x41" + . "\xec\x00\x10\x00\x41\xef\x00\x10\x00\x41\x2c\x10\x00\x41\x20\x10" + . "\x00\x41\xd7\x00\x10\x00\x41\xef\x00\x10\x00\x41\xf2\x00\x10\x00" + . "\x41\xec\x00\x10\x00\x41\xe4\x00\x10\x00\x41\x21\x10\x00\x41\x0a" + . "\x10\x00\x0b"); +$module = (new Decoder(new BlobStream($wasmBinary)))->decode(); + +$store = Store::empty(); +$linker = new Linker($store); + +$linker->register('', 'putc', Extern::Func(FuncInst::Host(new FuncType([ValType::I32], []), function (Runtime $runtime, int $c) { printf('%c', $c); }))); + +$runtime = Runtime::instantiate($store, $module, $linker->resolve($module)); + +$runtime->invoke('main', []); diff --git a/phpstan.neon b/phpstan.neon index a3d6227..fd3341e 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -8,6 +8,7 @@ parameters: tipsOfTheDay: false paths: - src + - examples/hello-world - examples/php-on-wasm typeAliases: Byte: 'int' diff --git a/src/Stream/BlobStream.php b/src/Stream/BlobStream.php new file mode 100644 index 0000000..972b8f6 --- /dev/null +++ b/src/Stream/BlobStream.php @@ -0,0 +1,95 @@ +<?php + +declare(strict_types=1); + +namespace Nsfisis\Waddiwasi\Stream; + +use function assert; +use function ord; +use function strlen; +use function substr; + +/** + * Read-only blob stream. + */ +final class BlobStream implements StreamInterface +{ + /** + * @var int<0, max> + */ + private int $pos = 0; + + /** + * @var positive-int + */ + private readonly int $len; + + /** + * Creates a new blob stream with the given content. + * + * @param non-empty-string $content + * The content of the blob. + */ + public function __construct( + private readonly string $content, + ) { + $this->len = strlen($content); + } + + public function close(): void + { + } + + public function read(int $bytes): string + { + $this->ensureNBytesAvailable($bytes); + $ret = substr($this->content, $this->pos, $bytes); + $this->pos += $bytes; + assert($ret !== ''); + return $ret; + } + + public function readByte(): int + { + $this->ensureNBytesAvailable(1); + return ord($this->content[$this->pos++]); + } + + public function peekByte(): int + { + $this->ensureNBytesAvailable(1); + return ord($this->content[$this->pos]); + } + + public function seek(int $bytes): void + { + $this->ensureNBytesAvailable($bytes); + $this->pos += $bytes; + } + + /** + * @phpstan-pure + */ + public function tell(): int + { + return $this->pos; + } + + /** + * @phpstan-pure + */ + public function eof(): bool + { + return $this->len <= $this->pos; + } + + /** + * @param positive-int $bytes + */ + private function ensureNBytesAvailable(int $bytes): void + { + if ($this->len < $this->pos + $bytes) { + throw new UnexpectedEofException(sprintf("Unexpected EOF while reading from blob (%d bytes expected, %d bytes read)", $bytes, $this->len - $this->pos)); + } + } +} diff --git a/src/Stream/StreamInterface.php b/src/Stream/StreamInterface.php index 0655d22..723c38b 100644 --- a/src/Stream/StreamInterface.php +++ b/src/Stream/StreamInterface.php @@ -15,7 +15,7 @@ interface StreamInterface * A binary string of $bytes bytes. * * @throws UnexpectedEofException - * Thrown if the stream does not have enough bytes to read. + * If the stream does not have enough bytes to read. * * @phpstan-impure */ @@ -28,7 +28,7 @@ interface StreamInterface * An 8-bit unsigned integer read from the stream. * * @throws UnexpectedEofException - * Thrown if the stream have reached the end. + * If the stream have reached the end. * * @phpstan-impure */ @@ -41,7 +41,7 @@ interface StreamInterface * An 8-bit unsigned integer read from the stream. * * @throws UnexpectedEofException - * Thrown if the stream have reached the end. + * If the stream have reached the end. * * @phpstan-impure */ @@ -53,7 +53,7 @@ interface StreamInterface * @param positive-int $bytes * * @throws UnexpectedEofException - * Thrown if the stream does not have enough bytes to seek. + * If the stream does not have enough bytes to seek. * * @phpstan-impure */ |
