diff --git a/tests/integration/runners.py b/tests/integration/runners.py index c1350ff..bb027f5 100644 --- a/tests/integration/runners.py +++ b/tests/integration/runners.py @@ -5,12 +5,10 @@ from typing import Any, Iterable, TextIO import ctypes import io -import os -import subprocess -import tempfile import pywasm.binary import wasm3 +import wasmer import wasmtime from phasm.compiler import phasm_compile @@ -18,31 +16,6 @@ from phasm.parser import phasm_parse from phasm import ourlang from phasm import wasm -def wat2wasm(code_wat: str) -> bytes: - """ - Converts the given WebAssembly Assembly code into WebAssembly Binary - """ - path = os.environ.get('WAT2WASM', 'wat2wasm') - - with tempfile.NamedTemporaryFile('w+t') as input_fp: - input_fp.write(code_wat) - input_fp.flush() - - with tempfile.NamedTemporaryFile('w+b') as output_fp: - subprocess.run( - [ - path, - input_fp.name, - '-o', - output_fp.name, - ], - check=True, - ) - - output_fp.seek(0) - - return output_fp.read() - class RunnerBase: """ Base class @@ -90,7 +63,7 @@ class RunnerBase: """ Compiles the WebAssembly AST into WebAssembly Binary """ - self.wasm_bin = wat2wasm(self.wasm_asm) + self.wasm_bin = wasmer.wat2wasm(self.wasm_asm) def interpreter_setup(self) -> None: """ @@ -253,6 +226,56 @@ class RunnerWasmtime(RunnerBase): return func(self.store, *args) +class RunnerWasmer(RunnerBase): + """ + Implements a runner for wasmer + + See https://pypi.org/project/wasmer/ + """ + + # pylint: disable=E1101 + + store: wasmer.Store + module: wasmer.Module + instance: wasmer.Instance + + def interpreter_setup(self) -> None: + self.store = wasmer.Store() + + def interpreter_load(self) -> None: + self.module = wasmer.Module(self.store, self.wasm_bin) + self.instance = wasmer.Instance(self.module) + + def interpreter_write_memory(self, offset: int, data: Iterable[int]) -> None: + exports = self.instance.exports + memory = getattr(exports, 'memory') + assert isinstance(memory, wasmer.Memory) + view = memory.uint8_view(offset) + + for idx, byt in enumerate(data): + view[idx] = byt + + def interpreter_read_memory(self, offset: int, length: int) -> bytes: + exports = self.instance.exports + memory = getattr(exports, 'memory') + assert isinstance(memory, wasmer.Memory) + view = memory.uint8_view(offset) + return bytes(view[offset:length]) + + def interpreter_dump_memory(self, textio: TextIO) -> None: + exports = self.instance.exports + memory = getattr(exports, 'memory') + assert isinstance(memory, wasmer.Memory) + view = memory.uint8_view() + + _dump_memory(textio, view) # type: ignore + + def call(self, function: str, *args: Any) -> Any: + exports = self.instance.exports + func = getattr(exports, function) + + return func(*args) + def _dump_memory(textio: TextIO, mem: bytes) -> None: line_width = 16