diff --git a/phasm/compiler.py b/phasm/compiler.py index b686dac..5ba2793 100644 --- a/phasm/compiler.py +++ b/phasm/compiler.py @@ -312,6 +312,12 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: if isinstance(inp, ourlang.Subscript): assert isinstance(inp.varref.type3, type3types.Type3), type3types.TYPE3_ASSERTION_ERROR + if inp.varref.type3 is type3types.bytes: + expression(wgn, inp.varref) + expression(wgn, inp.index) + wgn.call(stdlib_types.__subscript_bytes__) + return + if isinstance(inp.varref.type3, type3types.AppliedType3): if inp.varref.type3.base == type3types.static_array: assert 1 == len(inp.varref.type3.args) diff --git a/phasm/type3/constraints.py b/phasm/type3/constraints.py index 34a0158..6307d90 100644 --- a/phasm/type3/constraints.py +++ b/phasm/type3/constraints.py @@ -394,7 +394,11 @@ class CanBeSubscriptedConstraint(ConstraintBase): SameTypeConstraint(self.type3.args[self.index.value], self.ret_type3, comment=f'Tuple subscript index {self.index.value}'), ] - # FIXME: bytes + if self.type3 is types.bytes: + return [ + SameTypeConstraint(types.u32, self.index_type3, comment='([]) :: bytes -> u32 -> u8'), + SameTypeConstraint(types.u8, self.ret_type3, comment='([]) :: bytes -> u32 -> u8'), + ] if self.type3.name in types.LOOKUP_TABLE: return Error(f'{self.type3.name} cannot be subscripted') diff --git a/tests/integration/test_lang/test_bytes.py b/tests/integration/test_lang/test_bytes.py index 6df111a..af3f78d 100644 --- a/tests/integration/test_lang/test_bytes.py +++ b/tests/integration/test_lang/test_bytes.py @@ -1,5 +1,7 @@ import pytest +from phasm.type3.entry import Type3Exception + from ..helpers import Suite @pytest.mark.integration_test @@ -51,3 +53,32 @@ def testEntry(f: bytes) -> u8: result = Suite(code_py).run_code(b'Short', b'Long' * 100) assert 0 == result.returned_value + +@pytest.mark.integration_test +def test_function_call_element_ok(): + code_py = """ +@exported +def testEntry(f: bytes) -> u8: + return helper(f[0]) + +def helper(x: u8) -> u8: + return x +""" + + result = Suite(code_py).run_code(b'Short') + + assert 83 == result.returned_value + +@pytest.mark.integration_test +def test_function_call_element_type_mismatch(): + code_py = """ +@exported +def testEntry(f: bytes) -> u64: + return helper(f[0]) + +def helper(x: u64) -> u64: + return x +""" + + with pytest.raises(Type3Exception, match=r'u64 must be u8 instead'): + Suite(code_py).run_code()