Feat: Use struct in tuple
This commit is contained in:
parent
16ec664cb6
commit
fd3939a680
@ -460,7 +460,9 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
|
|||||||
|
|
||||||
expression(wgn, inp.varref)
|
expression(wgn, inp.varref)
|
||||||
|
|
||||||
if isinstance(el_type, type3types.AppliedType3) and el_type.base is type3types.tuple:
|
if isinstance(el_type, type3types.StructType3):
|
||||||
|
mtyp = 'i32'
|
||||||
|
elif isinstance(el_type, type3types.AppliedType3) and el_type.base is type3types.tuple:
|
||||||
mtyp = 'i32'
|
mtyp = 'i32'
|
||||||
else:
|
else:
|
||||||
assert isinstance(el_type, type3types.PrimitiveType3), NotImplementedError('Tuple of applied types / structs')
|
assert isinstance(el_type, type3types.PrimitiveType3), NotImplementedError('Tuple of applied types / structs')
|
||||||
|
|||||||
@ -85,9 +85,9 @@ class ConstantTuple(ConstantMemoryStored):
|
|||||||
"""
|
"""
|
||||||
__slots__ = ('value', )
|
__slots__ = ('value', )
|
||||||
|
|
||||||
value: List[Union[ConstantPrimitive, ConstantBytes, 'ConstantTuple']]
|
value: List[Union[ConstantPrimitive, ConstantBytes, 'ConstantTuple', 'ConstantStruct']]
|
||||||
|
|
||||||
def __init__(self, value: List[Union[ConstantPrimitive, ConstantBytes, 'ConstantTuple']], data_block: 'ModuleDataBlock') -> None:
|
def __init__(self, value: List[Union[ConstantPrimitive, ConstantBytes, 'ConstantTuple', 'ConstantStruct']], data_block: 'ModuleDataBlock') -> None:
|
||||||
super().__init__(data_block)
|
super().__init__(data_block)
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
@ -104,9 +104,9 @@ class ConstantStruct(ConstantMemoryStored):
|
|||||||
__slots__ = ('struct_name', 'value', )
|
__slots__ = ('struct_name', 'value', )
|
||||||
|
|
||||||
struct_name: str
|
struct_name: str
|
||||||
value: List[Union[ConstantPrimitive, ConstantBytes, ConstantTuple]]
|
value: List[Union[ConstantPrimitive, ConstantBytes, ConstantTuple, 'ConstantStruct']]
|
||||||
|
|
||||||
def __init__(self, struct_name: str, value: List[Union[ConstantPrimitive, ConstantBytes, ConstantTuple]], data_block: 'ModuleDataBlock') -> None:
|
def __init__(self, struct_name: str, value: List[Union[ConstantPrimitive, ConstantBytes, ConstantTuple, 'ConstantStruct']], data_block: 'ModuleDataBlock') -> None:
|
||||||
super().__init__(data_block)
|
super().__init__(data_block)
|
||||||
self.struct_name = struct_name
|
self.struct_name = struct_name
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|||||||
@ -208,14 +208,12 @@ class OurVisitor:
|
|||||||
_raise_static_error(node.target, 'Must be store context')
|
_raise_static_error(node.target, 'Must be store context')
|
||||||
|
|
||||||
if isinstance(node.value, ast.Constant):
|
if isinstance(node.value, ast.Constant):
|
||||||
type3 = self.visit_type(module, node.annotation)
|
|
||||||
|
|
||||||
value_data = self.visit_Module_Constant(module, node.value)
|
value_data = self.visit_Module_Constant(module, node.value)
|
||||||
|
|
||||||
return ModuleConstantDef(
|
return ModuleConstantDef(
|
||||||
node.target.id,
|
node.target.id,
|
||||||
node.lineno,
|
node.lineno,
|
||||||
type3,
|
self.visit_type(module, node.annotation),
|
||||||
value_data,
|
value_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -233,41 +231,16 @@ class OurVisitor:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if isinstance(node.value, ast.Call):
|
if isinstance(node.value, ast.Call):
|
||||||
# Struct constant
|
value_data = self.visit_Module_Constant(module, node.value)
|
||||||
# Stored in memory like a tuple, so much of the code is the same
|
|
||||||
|
|
||||||
if not isinstance(node.value.func, ast.Name):
|
assert isinstance(value_data, ConstantStruct) # type hint
|
||||||
_raise_static_error(node.value.func, 'Must be name')
|
|
||||||
if not isinstance(node.value.func.ctx, ast.Load):
|
|
||||||
_raise_static_error(node.value.func, 'Must be load context')
|
|
||||||
|
|
||||||
if not node.value.func.id in module.struct_definitions:
|
|
||||||
_raise_static_error(node.value.func, 'Undefined struct')
|
|
||||||
|
|
||||||
if node.value.keywords:
|
|
||||||
_raise_static_error(node.value.func, 'Cannot use keywords')
|
|
||||||
|
|
||||||
if not isinstance(node.annotation, ast.Name):
|
|
||||||
_raise_static_error(node.annotation, 'Must be name')
|
|
||||||
|
|
||||||
struct_data = [
|
|
||||||
self.visit_Module_Constant(module, arg_node)
|
|
||||||
for arg_node in node.value.args
|
|
||||||
if isinstance(arg_node, ast.Constant)
|
|
||||||
]
|
|
||||||
if len(node.value.args) != len(struct_data):
|
|
||||||
_raise_static_error(node, 'Struct arguments must be constants')
|
|
||||||
|
|
||||||
# Allocate the data
|
|
||||||
data_block = ModuleDataBlock(struct_data)
|
|
||||||
module.data.blocks.append(data_block)
|
|
||||||
|
|
||||||
# Then return the constant as a pointer
|
# Then return the constant as a pointer
|
||||||
return ModuleConstantDef(
|
return ModuleConstantDef(
|
||||||
node.target.id,
|
node.target.id,
|
||||||
node.lineno,
|
node.lineno,
|
||||||
self.visit_type(module, node.annotation),
|
self.visit_type(module, node.annotation),
|
||||||
ConstantStruct(node.value.func.id, struct_data, data_block),
|
value_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
raise NotImplementedError(f'{node} on Module AnnAssign')
|
raise NotImplementedError(f'{node} on Module AnnAssign')
|
||||||
@ -561,12 +534,12 @@ class OurVisitor:
|
|||||||
|
|
||||||
return Subscript(varref, slice_expr)
|
return Subscript(varref, slice_expr)
|
||||||
|
|
||||||
def visit_Module_Constant(self, module: Module, node: Union[ast.Constant, ast.Tuple]) -> Union[ConstantPrimitive, ConstantBytes, ConstantTuple]:
|
def visit_Module_Constant(self, module: Module, node: Union[ast.Constant, ast.Tuple, ast.Call]) -> Union[ConstantPrimitive, ConstantBytes, ConstantTuple, ConstantStruct]:
|
||||||
if isinstance(node, ast.Tuple):
|
if isinstance(node, ast.Tuple):
|
||||||
tuple_data = [
|
tuple_data = [
|
||||||
self.visit_Module_Constant(module, arg_node)
|
self.visit_Module_Constant(module, arg_node)
|
||||||
for arg_node in node.elts
|
for arg_node in node.elts
|
||||||
if isinstance(arg_node, (ast.Constant, ast.Tuple, ))
|
if isinstance(arg_node, (ast.Constant, ast.Tuple, ast.Call, ))
|
||||||
]
|
]
|
||||||
|
|
||||||
if len(node.elts) != len(tuple_data):
|
if len(node.elts) != len(tuple_data):
|
||||||
@ -578,6 +551,33 @@ class OurVisitor:
|
|||||||
|
|
||||||
return ConstantTuple(tuple_data, data_block)
|
return ConstantTuple(tuple_data, data_block)
|
||||||
|
|
||||||
|
if isinstance(node, ast.Call):
|
||||||
|
# Struct constant
|
||||||
|
# Stored in memory like a tuple, so much of the code is the same
|
||||||
|
|
||||||
|
if not isinstance(node.func, ast.Name):
|
||||||
|
_raise_static_error(node.func, 'Must be name')
|
||||||
|
if not isinstance(node.func.ctx, ast.Load):
|
||||||
|
_raise_static_error(node.func, 'Must be load context')
|
||||||
|
|
||||||
|
if not node.func.id in module.struct_definitions:
|
||||||
|
_raise_static_error(node.func, 'Undefined struct')
|
||||||
|
|
||||||
|
if node.keywords:
|
||||||
|
_raise_static_error(node.func, 'Cannot use keywords')
|
||||||
|
|
||||||
|
struct_data = [
|
||||||
|
self.visit_Module_Constant(module, arg_node)
|
||||||
|
for arg_node in node.args
|
||||||
|
if isinstance(arg_node, (ast.Constant, ast.Tuple, ast.Call, ))
|
||||||
|
]
|
||||||
|
if len(node.args) != len(struct_data):
|
||||||
|
_raise_static_error(node, 'Struct arguments must be constants')
|
||||||
|
|
||||||
|
data_block = ModuleDataBlock(struct_data)
|
||||||
|
module.data.blocks.append(data_block)
|
||||||
|
return ConstantStruct(node.func.id, struct_data, data_block)
|
||||||
|
|
||||||
_not_implemented(node.kind is None, 'Constant.kind')
|
_not_implemented(node.kind is None, 'Constant.kind')
|
||||||
|
|
||||||
if isinstance(node.value, (int, float, )):
|
if isinstance(node.value, (int, float, )):
|
||||||
|
|||||||
@ -162,6 +162,29 @@ def testEntry() -> u8:
|
|||||||
|
|
||||||
assert 0x41 == result.returned_value
|
assert 0x41 == result.returned_value
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
def test_struct_as_part_of_tuple():
|
||||||
|
code_py = """
|
||||||
|
class ValueStruct:
|
||||||
|
value: i32
|
||||||
|
|
||||||
|
CONSTANT: (ValueStruct, u64, ) = (ValueStruct(234), 19, )
|
||||||
|
|
||||||
|
def l0(c: ValueStruct) -> i32:
|
||||||
|
return c.value
|
||||||
|
|
||||||
|
def l1(c: (ValueStruct, u64, )) -> i32:
|
||||||
|
return l0(c[0])
|
||||||
|
|
||||||
|
@exported
|
||||||
|
def testEntry() -> i32:
|
||||||
|
return l1(CONSTANT)
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
|
assert 234 == 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 = """
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user