From 1536ea0bbb31234b87b50f9b3c11d3cf6649b7f5 Mon Sep 17 00:00:00 2001 From: "Johan B.W. de Vries" Date: Fri, 10 Nov 2023 14:53:48 +0100 Subject: [PATCH] Enable use of bytes in constants Including using them in tuple constants. --- phasm/codestyle.py | 3 +++ phasm/compiler.py | 18 ++++++++++++++---- phasm/ourlang.py | 3 +++ tests/integration/test_lang/test_bytes.py | 14 ++++++++++++++ tests/integration/test_lang/test_tuple.py | 20 ++++++++++++++++++++ 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/phasm/codestyle.py b/phasm/codestyle.py index c984937..ea5c207 100644 --- a/phasm/codestyle.py +++ b/phasm/codestyle.py @@ -68,6 +68,9 @@ def expression(inp: ourlang.Expression) -> str: # could not fit in the given float type return str(inp.value) + if isinstance(inp, ourlang.ConstantBytes): + return repr(inp.value) + if isinstance(inp, ourlang.ConstantTuple): return '(' + ', '.join( expression(x) diff --git a/phasm/compiler.py b/phasm/compiler.py index b7f45fa..b4ebd20 100644 --- a/phasm/compiler.py +++ b/phasm/compiler.py @@ -22,6 +22,8 @@ LOAD_STORE_TYPE_MAP = { 'u64': 'i64', 'f32': 'f32', 'f64': 'f64', + + 'bytes': 'i32', # Bytes are passed around as pointers } def phasm_compile(inp: ourlang.Module) -> wasm.Module: @@ -237,7 +239,6 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: raise NotImplementedError(f'Constants with type {inp.type3:s}') if isinstance(inp, ourlang.ConstantBytes): - assert inp.data_block is not None, 'Bytes must be memory stored' assert inp.data_block.address is not None, 'Value not allocated' wgn.i32.const(inp.data_block.address) return @@ -742,9 +743,18 @@ def module_data(inp: ourlang.ModuleData) -> bytes: continue if constant.type3 == type3types.bytes: - assert isinstance(constant.value, bytes) - data_list.append(module_data_u32(len(constant.value))) - data_list.append(constant.value) + assert isinstance(constant, ourlang.ConstantBytes) + + if block is not constant.data_block: + # It's stored in a different block + # We only need to store its address + # This happens for example when a tuple refers + # to a bytes constant + assert constant.data_block.address is not None + data_list.append(module_data_u32(constant.data_block.address)) + else: + data_list.append(module_data_u32(len(constant.value))) + data_list.append(constant.value) continue raise NotImplementedError(constant, constant.type3, constant.value) diff --git a/phasm/ourlang.py b/phasm/ourlang.py index 9561590..d3ca565 100644 --- a/phasm/ourlang.py +++ b/phasm/ourlang.py @@ -62,6 +62,9 @@ class ConstantBytes(Constant): self.data_block = data_block def __repr__(self) -> str: + # Do not repr the whole ModuleDataBlock + # As this has a reference back to this constant for its data + # which it needs to compile the data into the program return f'ConstantBytes({repr(self.value)}, @{repr(self.data_block.address)})' class ConstantTuple(Constant): diff --git a/tests/integration/test_lang/test_bytes.py b/tests/integration/test_lang/test_bytes.py index af3f78d..6a3fe07 100644 --- a/tests/integration/test_lang/test_bytes.py +++ b/tests/integration/test_lang/test_bytes.py @@ -42,6 +42,20 @@ def testEntry(f: bytes) -> u8: assert 0x61 == result.returned_value +@pytest.mark.integration_test +def test_constant(): + code_py = """ +CONSTANT: bytes = b'ABCDEF' + +@exported +def testEntry() -> u8: + return CONSTANT[0] +""" + + result = Suite(code_py).run_code() + + assert 0x41 == result.returned_value + @pytest.mark.integration_test def test_bytes_index_out_of_bounds(): code_py = """ diff --git a/tests/integration/test_lang/test_tuple.py b/tests/integration/test_lang/test_tuple.py index bf8033d..21bb86e 100644 --- a/tests/integration/test_lang/test_tuple.py +++ b/tests/integration/test_lang/test_tuple.py @@ -119,6 +119,26 @@ def testEntry() -> u64: assert 128 == result.returned_value +@pytest.mark.integration_test +def test_bytes_as_part_of_tuple(): + code_py = """ +CONSTANT: (bytes, u64, ) = (b'ABCDEF', 19, ) + +def l0(c: bytes) -> u8: + return c[0] + +def l1(c: (bytes, u64, )) -> u8: + return l0(c[0]) + +@exported +def testEntry() -> u8: + return l1(CONSTANT) +""" + + result = Suite(code_py).run_code() + + assert 0x41 == result.returned_value + @pytest.mark.integration_test def test_function_call_element_type_mismatch(): code_py = """