diff --git a/Makefile b/Makefile index 8f4d045..ad186c2 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ examples: venv/.done $(subst .py,.wasm,$(wildcard examples/*.py)) $(subst .py,.w venv/bin/python3 -m http.server --directory examples test: venv/.done - WAT2WASM=$(WAT2WASM) venv/bin/pytest tests $(TEST_FLAGS) + venv/bin/pytest tests $(TEST_FLAGS) lint: venv/.done venv/bin/pylint phasm diff --git a/README.md b/README.md index 5ab49f7..c9cb056 100644 --- a/README.md +++ b/README.md @@ -3,19 +3,97 @@ phasm Elevator pitch -------------- -A language that looks like Python, handles like Haskell, and compiles to -WebAssembly. +A programming language, that looks like Python, handles like Haskell, +and compiles directly to WebAssembly. -Naming ------- +Project state +------------- +This is a hobby project for now. Use at your own risk. + +How to run +---------- +You should only need make and python3. Currently, we're working with python3.8, +since we're using the python ast parser, it might not work on other versions. + +To run the examples: +```sh +make examples +``` + +To run the tests: +```sh +make test +``` + +To run the linting and type checking: +```sh +make lint typecheck +``` + +To compile a Phasm file: +```sh +python3.8 -m phasm source.py output.wat +``` + +Additional required tools +------------------------- +At the moment, the compiler outputs WebAssembly text format. To actually +get a binary, you will need the wat2wasm tool[6]. + +Example +------- +For more examples, see the examples directory. +```py +def helper(n: u64, a: u64, b: u64) -> u64: + if n < 1: + return a + b + + return helper(n - 1, a + b, a) + +@exported +def fib(n: u64) -> u64: + if n == 0: + return 0 + + if n == 1: + return 1 + + return helper(n - 1, 0, 1) +``` + +Gotcha's +-------- +- When importing and exporting unsigned values to WebAssembly, they will become + signed, as WebAssembly has no native unsigned type. You may need to cast + or reinterpret them. +- Currently, Phasm files have the .py extension, which helps with syntax + highlighting, that might change in the future. + +Contributing +------------ +At this time, we're mostly looking for use cases for WebAssembly, other than to +compile existing C code and running them in the browser. The goal of WebAssembly +is to enable high-performance applications on web pages[5]. Though most people +seem to use it to have existing code run in the browser. + +If you have a situation where WebAssembly would be useful for it's speed, we're +interested to see what you want to use it for. + +Also, if you are trying out Phasm, and you're running into a limitation, we're +interested in a minimal test case that shows what you want to achieve and how +Phasm currently fails you. + +Name origin +----------- - p from python - ha from Haskell - asm from WebAssembly -You will need wat2wasm from github.com/WebAssembly/wabt in your path. - -Ideas -===== -- https://github.com/wasmerio/wasmer-python -- https://github.com/diekmann/wasm-fizzbuzz -- https://blog.scottlogic.com/2018/04/26/webassembly-by-hand.html +References +---------- +[1] https://www.python.org/ +[2] https://www.haskell.org/ +[3] https://webassembly.org/ +[4] https://www.w3.org/TR/wasm-core-1/ +[5] https://en.wikipedia.org/w/index.php?title=WebAssembly&oldid=1103639883 +[6] https://github.com/WebAssembly/wabt diff --git a/TODO.md b/TODO.md index 41ae3da..0da4619 100644 --- a/TODO.md +++ b/TODO.md @@ -4,3 +4,5 @@ - Implement a proper type matching / checking system - Check if we can use DataView in the Javascript examples, e.g. with setUint32 - Storing u8 in memory still claims 32 bits (since that's what you need in local variables). However, using load8_u / loadu_s we can optimize this. +- Implement a FizzBuzz example +- Also, check the codes for FIXME and TODO diff --git a/examples/fib.py b/examples/fib.py index 8536245..af435c1 100644 --- a/examples/fib.py +++ b/examples/fib.py @@ -1,11 +1,11 @@ -def helper(n: i64, a: i64, b: i64) -> i64: +def helper(n: u64, a: u64, b: u64) -> u64: if n < 1: return a + b return helper(n - 1, a + b, a) @exported -def fib(n: i64) -> i64: +def fib(n: u64) -> u64: if n == 0: return 0 @@ -15,5 +15,5 @@ def fib(n: i64) -> i64: return helper(n - 1, 0, 1) @exported -def testEntry() -> i64: +def testEntry() -> u64: return fib(40) diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index 2858472..ca4c8a7 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -1,49 +1,11 @@ -import io -import os -import subprocess import sys -from tempfile import NamedTemporaryFile - -import pywasm - -import wasm3 - -import wasmer -import wasmer_compiler_cranelift - -import wasmtime - from phasm.codestyle import phasm_render -from phasm.compiler import phasm_compile -from phasm.parser import phasm_parse from . import runners DASHES = '-' * 16 -def wat2wasm(code_wat): - path = os.environ.get('WAT2WASM', 'wat2wasm') - - with NamedTemporaryFile('w+t') as input_fp: - input_fp.write(code_wat) - input_fp.flush() - - with 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 SuiteResult: def __init__(self): self.returned_value = None diff --git a/tests/integration/test_helper.py b/tests/integration/test_helper.py index 387eb5a..cb44021 100644 --- a/tests/integration/test_helper.py +++ b/tests/integration/test_helper.py @@ -5,7 +5,7 @@ import pytest from pywasm import binary from pywasm import Runtime -from .helpers import wat2wasm +from wasmer import wat2wasm def run(code_wat): code_wasm = wat2wasm(code_wat)