MVP #1
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,2 +1,5 @@
|
|||||||
*.wasm
|
/*.wasm
|
||||||
*.wat
|
/*.wat
|
||||||
|
/venv
|
||||||
|
|
||||||
|
__pycache__
|
||||||
|
|||||||
8
Makefile
8
Makefile
@ -6,3 +6,11 @@
|
|||||||
|
|
||||||
server:
|
server:
|
||||||
python3.8 -m http.server
|
python3.8 -m http.server
|
||||||
|
|
||||||
|
test: venv/.done
|
||||||
|
venv/bin/pytest tests
|
||||||
|
|
||||||
|
venv/.done: requirements.txt
|
||||||
|
python3.8 -m venv venv
|
||||||
|
venv/bin/python3 -m pip install -r $^
|
||||||
|
touch $@
|
||||||
|
|||||||
17
compile.py
17
compile.py
@ -138,17 +138,22 @@ class Visitor(ast.NodeVisitor):
|
|||||||
def err(msg: str) -> None:
|
def err(msg: str) -> None:
|
||||||
sys.stderr.write('{}\n'.format(msg))
|
sys.stderr.write('{}\n'.format(msg))
|
||||||
|
|
||||||
def main(source: str, sink: str) -> int:
|
def process(input: str, input_name: str) -> str:
|
||||||
with open(source, 'r') as fil:
|
res = ast.parse(input, input_name)
|
||||||
code = fil.read()
|
|
||||||
|
|
||||||
res = ast.parse(code, source)
|
|
||||||
|
|
||||||
visitor = Visitor()
|
visitor = Visitor()
|
||||||
visitor.visit(res)
|
visitor.visit(res)
|
||||||
|
|
||||||
|
return visitor.generate()
|
||||||
|
|
||||||
|
def main(source: str, sink: str) -> int:
|
||||||
|
with open(source, 'r') as fil:
|
||||||
|
code_py = fil.read()
|
||||||
|
|
||||||
|
code_wat = process(code_py, source)
|
||||||
|
|
||||||
with open(sink, 'w') as fil:
|
with open(sink, 'w') as fil:
|
||||||
fil.write(visitor.generate())
|
fil.write(code_wat)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
20
func.html
20
func.html
@ -1,20 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Simple add example</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<script>
|
|
||||||
|
|
||||||
WebAssembly.instantiateStreaming(fetch('func.wasm'))
|
|
||||||
.then(obj => {
|
|
||||||
console.log(obj.instance.exports.add(1, 2)); // "3"
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
29
log.html
29
log.html
@ -1,29 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Simple log example</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<script>
|
|
||||||
|
|
||||||
var importObject = {
|
|
||||||
console: {
|
|
||||||
log: function(arg) {
|
|
||||||
console.log(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WebAssembly.instantiateStreaming(fetch('log.wasm'), importObject)
|
|
||||||
.then(obj => {
|
|
||||||
obj.instance.exports.logIt();
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
6
log.py
6
log.py
@ -1,6 +0,0 @@
|
|||||||
@external('console')
|
|
||||||
def log(msg: i32) -> None:
|
|
||||||
...
|
|
||||||
|
|
||||||
def logIt():
|
|
||||||
log(13 + 13 * 123)
|
|
||||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pywasm==1.0.7
|
||||||
|
pytest==6.2.2
|
||||||
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
0
tests/integration/__init__.py
Normal file
0
tests/integration/__init__.py
Normal file
85
tests/integration/test_fib.py
Normal file
85
tests/integration/test_fib.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import io
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from tempfile import NamedTemporaryFile
|
||||||
|
|
||||||
|
from pywasm import binary
|
||||||
|
from pywasm import Runtime
|
||||||
|
|
||||||
|
from compile import process
|
||||||
|
|
||||||
|
def wat2wasm(code_wat):
|
||||||
|
with NamedTemporaryFile('w+t') as input_fp:
|
||||||
|
input_fp.write(code_wat)
|
||||||
|
input_fp.flush()
|
||||||
|
|
||||||
|
with NamedTemporaryFile('w+b') as output_fp:
|
||||||
|
result = subprocess.run(
|
||||||
|
[
|
||||||
|
'wat2wasm',
|
||||||
|
input_fp.name,
|
||||||
|
'-o',
|
||||||
|
output_fp.name,
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
output_fp.seek(0)
|
||||||
|
|
||||||
|
return output_fp.read()
|
||||||
|
|
||||||
|
class SuiteResult:
|
||||||
|
def __init__(self):
|
||||||
|
self.log_int32_list = []
|
||||||
|
|
||||||
|
def callback_log_int32(self, store, value):
|
||||||
|
del store # auto passed by pywasm
|
||||||
|
|
||||||
|
self.log_int32_list.append(value)
|
||||||
|
|
||||||
|
def make_imports(self):
|
||||||
|
return {
|
||||||
|
'console': {
|
||||||
|
'logInt32': self.callback_log_int32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Suite:
|
||||||
|
def __init__(self, code_py, test_name):
|
||||||
|
self.code_py = code_py
|
||||||
|
self.test_name = test_name
|
||||||
|
|
||||||
|
def run_code(self, *args):
|
||||||
|
"""
|
||||||
|
Compiles the given python code into wasm and
|
||||||
|
then runs it
|
||||||
|
|
||||||
|
Returned is an object with the results set
|
||||||
|
"""
|
||||||
|
code_wat = process(self.code_py, self.test_name)
|
||||||
|
sys.stderr.write(code_wat)
|
||||||
|
|
||||||
|
code_wasm = wat2wasm(code_wat)
|
||||||
|
module = binary.Module.from_reader(io.BytesIO(code_wasm))
|
||||||
|
|
||||||
|
result = SuiteResult()
|
||||||
|
runtime = Runtime(module, result.make_imports(), {})
|
||||||
|
|
||||||
|
result.returned_value = runtime.exec('testEntry', args)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def test_fib():
|
||||||
|
code_py = """
|
||||||
|
@external('console')
|
||||||
|
def logInt32(value: i32) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
def testEntry():
|
||||||
|
logInt32(13 + 13 * 123)
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py, 'test_fib').run_code()
|
||||||
|
|
||||||
|
assert None is result.returned_value
|
||||||
|
assert [1612] == result.log_int32_list
|
||||||
Loading…
x
Reference in New Issue
Block a user