Enable use of bytes in constants

Including using them in tuple constants.
This commit is contained in:
Johan B.W. de Vries 2023-11-10 14:53:48 +01:00
parent 20d177e2c5
commit 1536ea0bbb
5 changed files with 54 additions and 4 deletions

View File

@ -68,6 +68,9 @@ def expression(inp: ourlang.Expression) -> str:
# could not fit in the given float type # could not fit in the given float type
return str(inp.value) return str(inp.value)
if isinstance(inp, ourlang.ConstantBytes):
return repr(inp.value)
if isinstance(inp, ourlang.ConstantTuple): if isinstance(inp, ourlang.ConstantTuple):
return '(' + ', '.join( return '(' + ', '.join(
expression(x) expression(x)

View File

@ -22,6 +22,8 @@ LOAD_STORE_TYPE_MAP = {
'u64': 'i64', 'u64': 'i64',
'f32': 'f32', 'f32': 'f32',
'f64': 'f64', 'f64': 'f64',
'bytes': 'i32', # Bytes are passed around as pointers
} }
def phasm_compile(inp: ourlang.Module) -> wasm.Module: 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}') raise NotImplementedError(f'Constants with type {inp.type3:s}')
if isinstance(inp, ourlang.ConstantBytes): 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' assert inp.data_block.address is not None, 'Value not allocated'
wgn.i32.const(inp.data_block.address) wgn.i32.const(inp.data_block.address)
return return
@ -742,7 +743,16 @@ def module_data(inp: ourlang.ModuleData) -> bytes:
continue continue
if constant.type3 == type3types.bytes: if constant.type3 == type3types.bytes:
assert isinstance(constant.value, bytes) 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(module_data_u32(len(constant.value)))
data_list.append(constant.value) data_list.append(constant.value)
continue continue

View File

@ -62,6 +62,9 @@ class ConstantBytes(Constant):
self.data_block = data_block self.data_block = data_block
def __repr__(self) -> str: 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)})' return f'ConstantBytes({repr(self.value)}, @{repr(self.data_block.address)})'
class ConstantTuple(Constant): class ConstantTuple(Constant):

View File

@ -42,6 +42,20 @@ def testEntry(f: bytes) -> u8:
assert 0x61 == result.returned_value 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 @pytest.mark.integration_test
def test_bytes_index_out_of_bounds(): def test_bytes_index_out_of_bounds():
code_py = """ code_py = """

View File

@ -119,6 +119,26 @@ def testEntry() -> u64:
assert 128 == result.returned_value 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 @pytest.mark.integration_test
def test_function_call_element_type_mismatch(): def test_function_call_element_type_mismatch():
code_py = """ code_py = """