Exposes Wasm's reinterpret function

This commit is contained in:
Johan B.W. de Vries 2025-05-25 13:45:18 +02:00
parent cfdcaa230d
commit 56ab88db2c
4 changed files with 114 additions and 0 deletions

View File

@ -551,6 +551,35 @@ instance_type_class(Promotable, f32, f64, methods={
'demote': stdtypes.f32_f64_demote, 'demote': stdtypes.f32_f64_demote,
}) })
Reinterpretable = Type3Class('Reinterpretable', (a, b, ), methods={
'reinterpret': [a, b]
}, operators={})
instance_type_class(Reinterpretable, u32, f32, methods={
'reinterpret': stdtypes.u32_f32_reinterpret,
})
instance_type_class(Reinterpretable, u64, f64, methods={
'reinterpret': stdtypes.u64_f64_reinterpret,
})
instance_type_class(Reinterpretable, i32, f32, methods={
'reinterpret': stdtypes.i32_f32_reinterpret,
})
instance_type_class(Reinterpretable, i64, f64, methods={
'reinterpret': stdtypes.i64_f64_reinterpret,
})
instance_type_class(Reinterpretable, f32, u32, methods={
'reinterpret': stdtypes.f32_u32_reinterpret,
})
instance_type_class(Reinterpretable, f64, u64, methods={
'reinterpret': stdtypes.f64_u64_reinterpret,
})
instance_type_class(Reinterpretable, f32, i32, methods={
'reinterpret': stdtypes.f32_i32_reinterpret,
})
instance_type_class(Reinterpretable, f64, i64, methods={
'reinterpret': stdtypes.f64_i64_reinterpret,
})
Foldable = Type3Class('Foldable', (t, ), methods={ Foldable = Type3Class('Foldable', (t, ), methods={
'sum': [t(a), a], 'sum': [t(a), a],
'foldl': [[b, a, b], b, t(a), b], 'foldl': [[b, a, b], b, t(a), b],
@ -621,5 +650,6 @@ PRELUDE_METHODS = {
**Sized_.methods, **Sized_.methods,
**Extendable.methods, **Extendable.methods,
**Promotable.methods, **Promotable.methods,
**Reinterpretable.methods,
**Foldable.methods, **Foldable.methods,
} }

View File

@ -1141,6 +1141,41 @@ def f32_f64_demote(g: Generator, tv_map: TypeVariableLookup) -> None:
del tv_map del tv_map
g.f32.demote_f64() g.f32.demote_f64()
## ###
## Reinterpretable
def i32_f32_reinterpret(g: Generator, tv_map: TypeVariableLookup) -> None:
del tv_map
g.f32.reinterpret_i32()
def u32_f32_reinterpret(g: Generator, tv_map: TypeVariableLookup) -> None:
del tv_map
g.f32.reinterpret_i32()
def i64_f64_reinterpret(g: Generator, tv_map: TypeVariableLookup) -> None:
del tv_map
g.f64.reinterpret_i64()
def u64_f64_reinterpret(g: Generator, tv_map: TypeVariableLookup) -> None:
del tv_map
g.f64.reinterpret_i64()
def f32_i32_reinterpret(g: Generator, tv_map: TypeVariableLookup) -> None:
del tv_map
g.i32.reinterpret_f32()
def f32_u32_reinterpret(g: Generator, tv_map: TypeVariableLookup) -> None:
del tv_map
g.i32.reinterpret_f32()
def f64_i64_reinterpret(g: Generator, tv_map: TypeVariableLookup) -> None:
del tv_map
g.i64.reinterpret_f64()
def f64_u64_reinterpret(g: Generator, tv_map: TypeVariableLookup) -> None:
del tv_map
g.i64.reinterpret_f64()
## ### ## ###
## Foldable ## Foldable

View File

@ -81,6 +81,7 @@ class Generator_i32(Generator_i32i64):
super().__init__('i32', generator) super().__init__('i32', generator)
# 2.4.1. Numeric Instructions # 2.4.1. Numeric Instructions
self.reinterpret_f32 = functools.partial(self.generator.add_statement, 'i32.reinterpret_f32')
self.wrap_i64 = functools.partial(self.generator.add_statement, 'i32.wrap_i64') self.wrap_i64 = functools.partial(self.generator.add_statement, 'i32.wrap_i64')
class Generator_i64(Generator_i32i64): class Generator_i64(Generator_i32i64):
@ -90,6 +91,7 @@ class Generator_i64(Generator_i32i64):
# 2.4.1. Numeric Instructions # 2.4.1. Numeric Instructions
self.extend_i32_s = functools.partial(self.generator.add_statement, 'i64.extend_i32_s') self.extend_i32_s = functools.partial(self.generator.add_statement, 'i64.extend_i32_s')
self.extend_i32_u = functools.partial(self.generator.add_statement, 'i64.extend_i32_u') self.extend_i32_u = functools.partial(self.generator.add_statement, 'i64.extend_i32_u')
self.reinterpret_f64 = functools.partial(self.generator.add_statement, 'i64.reinterpret_f64')
class Generator_f32f64: class Generator_f32f64:
def __init__(self, prefix: str, generator: 'Generator') -> None: def __init__(self, prefix: str, generator: 'Generator') -> None:
@ -143,6 +145,7 @@ class Generator_f32(Generator_f32f64):
# 2.4.1 Numeric Instructions # 2.4.1 Numeric Instructions
self.demote_f64 = functools.partial(self.generator.add_statement, 'f32.demote_f64') self.demote_f64 = functools.partial(self.generator.add_statement, 'f32.demote_f64')
self.reinterpret_i32 = functools.partial(self.generator.add_statement, 'f32.reinterpret_i32')
class Generator_f64(Generator_f32f64): class Generator_f64(Generator_f32f64):
def __init__(self, generator: 'Generator') -> None: def __init__(self, generator: 'Generator') -> None:
@ -150,6 +153,8 @@ class Generator_f64(Generator_f32f64):
# 2.4.1 Numeric Instructions # 2.4.1 Numeric Instructions
self.promote_f32 = functools.partial(self.generator.add_statement, 'f64.promote_f32') self.promote_f32 = functools.partial(self.generator.add_statement, 'f64.promote_f32')
self.reinterpret_i64 = functools.partial(self.generator.add_statement, 'f64.reinterpret_i64')
self.reinterpret_i64 = functools.partial(self.generator.add_statement, 'f64.reinterpret_i64')
class Generator_Local: class Generator_Local:
def __init__(self, generator: 'Generator') -> None: def __init__(self, generator: 'Generator') -> None:

View File

@ -0,0 +1,44 @@
import pytest
from phasm.type3.entry import Type3Exception
from ..helpers import Suite
@pytest.mark.integration_test
def test_reinterpret_not_implemented():
code_py = """
class Foo:
val: i32
class Baz:
val: i32
@exported
def testEntry(x: Foo) -> Baz:
return reinterpret(x)
"""
with pytest.raises(Type3Exception, match='Missing type class instantation: Reinterpretable Foo Baz'):
Suite(code_py).run_code()
@pytest.mark.integration_test
@pytest.mark.parametrize('in_typ, in_val, out_typ, exp_val', [
('u32', 3225944128, 'f32', -3.1250152587890625, ),
('u64', 13837591364432297984, 'f64', -3.1250152587890625, ),
('i32', -1069023168, 'f32', -3.1250152587890625, ),
('i64', -4609152709277253632, 'f64', -3.1250152587890625, ),
('f32', -3.1250152587890625, 'u32', 3225944128, ),
('f64', -3.1250152587890625, 'u64', 13837591364432297984, ),
('f32', -3.1250152587890625, 'i32', -1069023168, ),
('f64', -3.1250152587890625, 'i64', -4609152709277253632, ),
])
def test_reinterpret_ok(in_typ, in_val, out_typ, exp_val):
code_py = f"""
@exported
def testEntry(x: {in_typ}) -> {out_typ}:
return reinterpret(x)
"""
result = Suite(code_py).run_code(in_val)
assert exp_val == result.returned_value