diff --git a/py2wasm/python.py b/py2wasm/python.py index 57d004e..77b53d2 100644 --- a/py2wasm/python.py +++ b/py2wasm/python.py @@ -373,10 +373,28 @@ class Visitor: assert isinstance(node.value, int) assert -2147483648 <= node.value <= 2147483647 - yield wasm.Statement( - '{}.const'.format(exp_type), - str(node.value) - ) + yield wasm.Statement('i32.const', str(node.value)) + return + + if 'i64' == exp_type: + assert isinstance(node.value, int) + assert -9223372036854775808 <= node.value <= 9223372036854775807 + + yield wasm.Statement('i64.const', str(node.value)) + return + + if 'f32' == exp_type: + assert isinstance(node.value, float) + # TODO: Size check? + + yield wasm.Statement('f32.const', node.value.hex()) + return + + if 'f64' == exp_type: + assert isinstance(node.value, float) + # TODO: Size check? + + yield wasm.Statement('f64.const', node.value.hex()) return raise NotImplementedError(exp_type) @@ -386,6 +404,17 @@ class Visitor: Visits a Name node as (part of) an expression """ assert node.id in wlocals + + if exp_type == 'i64' and wlocals[node.id] == 'i32': + yield wasm.Statement('local.get', '${}'.format(node.id)) + yield wasm.Statement('i64.extend_i32_s') + return + + if exp_type == 'f64' and wlocals[node.id] == 'f32': + yield wasm.Statement('local.get', '${}'.format(node.id)) + yield wasm.Statement('f64.promote_f32') + return + assert exp_type == wlocals[node.id] yield wasm.Statement( 'local.get', @@ -442,5 +471,5 @@ def _parse_annotation(ann: Optional[ast.expr]) -> str: assert ann is not None, 'Web Assembly requires type annotations' assert isinstance(ann, ast.Name) result = ann.id - assert result in ['i32'] + assert result in ['i32', 'i64', 'f32', 'f64'] return result diff --git a/tests/integration/test_simple.py b/tests/integration/test_simple.py index af73c4d..7650c6c 100644 --- a/tests/integration/test_simple.py +++ b/tests/integration/test_simple.py @@ -3,7 +3,7 @@ import pytest from .helpers import Suite @pytest.mark.integration_test -def test_return(): +def test_return_i32(): code_py = """ @exported def testEntry() -> i32: @@ -15,6 +15,45 @@ def testEntry() -> i32: assert 13 == result.returned_value assert [] == result.log_int32_list +@pytest.mark.integration_test +def test_return_i64(): + code_py = """ +@exported +def testEntry() -> i64: + return 13 +""" + + result = Suite(code_py, 'test_return').run_code() + + assert 13 == result.returned_value + assert [] == result.log_int32_list + +@pytest.mark.integration_test +def test_return_f32(): + code_py = """ +@exported +def testEntry() -> f32: + return 13.5 +""" + + result = Suite(code_py, 'test_return').run_code() + + assert 13.5 == result.returned_value + assert [] == result.log_int32_list + +@pytest.mark.integration_test +def test_return_f64(): + code_py = """ +@exported +def testEntry() -> f64: + return 13.5 +""" + + result = Suite(code_py, 'test_return').run_code() + + assert 13.5 == result.returned_value + assert [] == result.log_int32_list + @pytest.mark.integration_test def test_arg(): code_py = """ @@ -28,6 +67,58 @@ def testEntry(a: i32) -> i32: assert 125 == result.returned_value assert [] == result.log_int32_list +@pytest.mark.integration_test +def test_i32_to_i64(): + code_py = """ +@exported +def testEntry(a: i32) -> i64: + return a +""" + + result = Suite(code_py, 'test_return').run_code(125) + + assert 125 == result.returned_value + assert [] == result.log_int32_list + +@pytest.mark.integration_test +def test_i32_plus_i64(): + code_py = """ +@exported +def testEntry(a: i32, b: i64) -> i64: + return a + b +""" + + result = Suite(code_py, 'test_return').run_code(125, 100) + + assert 225 == result.returned_value + assert [] == result.log_int32_list + +@pytest.mark.integration_test +def test_f32_to_f64(): + code_py = """ +@exported +def testEntry(a: f32) -> f64: + return a +""" + + result = Suite(code_py, 'test_return').run_code(125.5) + + assert 125.5 == result.returned_value + assert [] == result.log_int32_list + +@pytest.mark.integration_test +def test_f32_plus_f64(): + code_py = """ +@exported +def testEntry(a: f32, b: f64) -> f64: + return a + b +""" + + result = Suite(code_py, 'test_return').run_code(125.5, 100.25) + + assert 225.75 == result.returned_value + assert [] == result.log_int32_list + @pytest.mark.integration_test def test_uadd(): code_py = """