More work on tuples
This commit is contained in:
parent
17f538d8cc
commit
25b5d6fc06
@ -203,14 +203,13 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
|
|||||||
wgn.i32.const(inp.variable.data_block.address)
|
wgn.i32.const(inp.variable.data_block.address)
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO: Broken after new type system
|
if inp.type3.base == type3types.tuple:
|
||||||
# if isinstance(inp.type, typing.TypeTuple):
|
assert inp.variable.data_block is not None, 'Tuples must be memory stored'
|
||||||
# assert isinstance(inp.definition.constant, ourlang.ConstantTuple)
|
assert inp.variable.data_block.address is not None, 'Value not allocated'
|
||||||
# assert inp.definition.data_block is not None, 'Combined values are memory stored'
|
wgn.i32.const(inp.variable.data_block.address)
|
||||||
# assert inp.definition.data_block.address is not None, 'Value not allocated'
|
return
|
||||||
# wgn.i32.const(inp.definition.data_block.address)
|
|
||||||
# return
|
raise NotImplementedError(expression, inp.variable, inp.type3.base)
|
||||||
#
|
|
||||||
|
|
||||||
assert inp.variable.data_block is None, 'Primitives are not memory stored'
|
assert inp.variable.data_block is None, 'Primitives are not memory stored'
|
||||||
|
|
||||||
@ -338,6 +337,30 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
|
|||||||
wgn.add_statement(f'{mtyp}.load')
|
wgn.add_statement(f'{mtyp}.load')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if inp.varref.type3.base == type3types.tuple:
|
||||||
|
assert isinstance(inp.index, ourlang.ConstantPrimitive)
|
||||||
|
assert isinstance(inp.index.value, int)
|
||||||
|
|
||||||
|
offset = 0
|
||||||
|
for el_type in inp.varref.type3.args[0:inp.index.value]:
|
||||||
|
assert isinstance(el_type, type3types.Type3), type3types.TYPE3_ASSERTION_ERROR
|
||||||
|
offset += _calculate_alloc_size(el_type)
|
||||||
|
|
||||||
|
# This doubles as the out of bounds check
|
||||||
|
el_type = inp.varref.type3.args[inp.index.value]
|
||||||
|
assert isinstance(el_type, type3types.Type3), type3types.TYPE3_ASSERTION_ERROR
|
||||||
|
|
||||||
|
expression(wgn, inp.varref)
|
||||||
|
|
||||||
|
mtyp = LOAD_STORE_TYPE_MAP.get(el_type.name)
|
||||||
|
if mtyp is None:
|
||||||
|
# In the future might extend this by having structs or tuples
|
||||||
|
# as members of struct or tuples
|
||||||
|
raise NotImplementedError(expression, inp, el_type)
|
||||||
|
|
||||||
|
wgn.add_statement(f'{mtyp}.load', f'offset={offset}')
|
||||||
|
return
|
||||||
|
|
||||||
raise NotImplementedError(expression, inp, inp.varref.type3)
|
raise NotImplementedError(expression, inp, inp.varref.type3)
|
||||||
|
|
||||||
if isinstance(inp, ourlang.AccessStructMember):
|
if isinstance(inp, ourlang.AccessStructMember):
|
||||||
|
|||||||
@ -379,6 +379,21 @@ class CanBeSubscriptedConstraint(ConstraintBase):
|
|||||||
SameTypeConstraint(self.type3.args[0], self.ret_type3, comment='([]) :: Subscriptable a => a b -> u32 -> b'),
|
SameTypeConstraint(self.type3.args[0], self.ret_type3, comment='([]) :: Subscriptable a => a b -> u32 -> b'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if self.type3.base == types.tuple:
|
||||||
|
if not isinstance(self.index, ourlang.ConstantPrimitive):
|
||||||
|
return Error('Must index with literal')
|
||||||
|
|
||||||
|
if not isinstance(self.index.value, int):
|
||||||
|
return Error('Must index with integer literal')
|
||||||
|
|
||||||
|
if self.index.value < 0 or len(self.type3.args) <= self.index.value:
|
||||||
|
return Error('Tuple index out of range')
|
||||||
|
|
||||||
|
return [
|
||||||
|
SameTypeConstraint(types.u32, self.index_type3, comment=f'Tuple subscript index {self.index.value}'),
|
||||||
|
SameTypeConstraint(self.type3.args[self.index.value], self.ret_type3, comment=f'Tuple subscript index {self.index.value}'),
|
||||||
|
]
|
||||||
|
|
||||||
# FIXME: bytes
|
# FIXME: bytes
|
||||||
|
|
||||||
if self.type3.name in types.LOOKUP_TABLE:
|
if self.type3.name in types.LOOKUP_TABLE:
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import pytest
|
|||||||
|
|
||||||
from phasm.type3.entry import Type3Exception
|
from phasm.type3.entry import Type3Exception
|
||||||
|
|
||||||
from ..constants import COMPLETE_NUMERIC_TYPES, TYPE_MAP
|
from ..constants import ALL_FLOAT_TYPES, COMPLETE_NUMERIC_TYPES, TYPE_MAP
|
||||||
from ..helpers import Suite
|
from ..helpers import Suite
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
@ -48,9 +48,42 @@ def testEntry() -> u32:
|
|||||||
|
|
||||||
assert 3333 == result.returned_value
|
assert 3333 == result.returned_value
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_function_call_element_ok():
|
||||||
|
code_py = """
|
||||||
|
CONSTANT: (u8, u32, u64, ) = (250, 250000, 250000000, )
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> u64:
|
||||||
|
return helper(CONSTANT[2])
|
||||||
|
|
||||||
|
def helper(x: u64) -> u64:
|
||||||
|
return x
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 250000000 == result.returned_value
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_function_call_element_type_mismatch():
|
||||||
|
code_py = """
|
||||||
|
CONSTANT: (u8, u32, u64, ) = (250, 250000, 250000000, )
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> u8:
|
||||||
|
return helper(CONSTANT[2])
|
||||||
|
|
||||||
|
def helper(x: u8) -> u8:
|
||||||
|
return x
|
||||||
|
"""
|
||||||
|
|
||||||
|
with pytest.raises(Type3Exception, match=r'u8 must be u64 instead'):
|
||||||
|
Suite(code_py).run_code()
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
@pytest.mark.parametrize('type_', COMPLETE_NUMERIC_TYPES)
|
@pytest.mark.parametrize('type_', COMPLETE_NUMERIC_TYPES)
|
||||||
def test_tuple_simple_constructor(type_):
|
def test_tuple_simple_constructor_int(type_):
|
||||||
code_py = f"""
|
code_py = f"""
|
||||||
@exported
|
@exported
|
||||||
def testEntry() -> {type_}:
|
def testEntry() -> {type_}:
|
||||||
@ -66,13 +99,14 @@ def helper(vector: ({type_}, {type_}, {type_}, )) -> {type_}:
|
|||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
def test_tuple_float():
|
@pytest.mark.parametrize('type_', ALL_FLOAT_TYPES)
|
||||||
code_py = """
|
def test_tuple_simple_constructor_float(type_):
|
||||||
|
code_py = f"""
|
||||||
@exported
|
@exported
|
||||||
def testEntry() -> f32:
|
def testEntry() -> {type_}:
|
||||||
return helper((1.0, 2.0, 3.0, ))
|
return helper((1.0, 2.0, 3.0, ))
|
||||||
|
|
||||||
def helper(v: (f32, f32, f32, )) -> f32:
|
def helper(v: ({type_}, {type_}, {type_}, )) -> {type_}:
|
||||||
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2])
|
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -139,7 +173,7 @@ def testEntry(x: (u8, u32, u64)) -> u64:
|
|||||||
return x[CONSTANT]
|
return x[CONSTANT]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with pytest.raises(Type3Exception, match='Tuples must be indexed with literals'):
|
with pytest.raises(Type3Exception, match='Must index with literal'):
|
||||||
Suite(code_py).run_code()
|
Suite(code_py).run_code()
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
@ -150,5 +184,5 @@ def testEntry(x: (u8, u32, u64)) -> u64:
|
|||||||
return x[0.0]
|
return x[0.0]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with pytest.raises(Type3Exception, match='Must be integer'):
|
with pytest.raises(Type3Exception, match='Must index with integer literal'):
|
||||||
Suite(code_py).run_code()
|
Suite(code_py).run_code()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user