Compare commits
1 Commits
e8e7acc102
...
3be4599fc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3be4599fc1 |
@ -15,10 +15,8 @@ from .type3.types import (
|
||||
IntType3,
|
||||
Type3,
|
||||
TypeApplication_Struct,
|
||||
TypeApplication_Type,
|
||||
TypeApplication_TypeInt,
|
||||
TypeApplication_TypeStar,
|
||||
TypeConstructor_DynamicArray,
|
||||
TypeConstructor_Function,
|
||||
TypeConstructor_StaticArray,
|
||||
TypeConstructor_Tuple,
|
||||
@ -111,25 +109,12 @@ def tuple_instantiation(wgn: WasmGenerator, mod: ourlang.Module, inp: ourlang.Tu
|
||||
|
||||
args: tuple[Type3, ...]
|
||||
|
||||
alloc_size_header = None
|
||||
|
||||
if isinstance(inp.type3.application, TypeApplication_Type):
|
||||
# Possibly paranoid assert. If we have a future variadic type,
|
||||
# does it also do this tuple instantation like this?
|
||||
assert isinstance(inp.type3.application.constructor, TypeConstructor_DynamicArray)
|
||||
|
||||
sa_type, = inp.type3.application.arguments
|
||||
|
||||
args = tuple(sa_type for _ in inp.elements)
|
||||
alloc_size = 4 + calculate_alloc_size(sa_type, is_member=False) * len(inp.elements)
|
||||
alloc_size_header = len(inp.elements)
|
||||
elif isinstance(inp.type3.application, TypeApplication_TypeStar):
|
||||
if isinstance(inp.type3.application, TypeApplication_TypeStar):
|
||||
# Possibly paranoid assert. If we have a future variadic type,
|
||||
# does it also do this tuple instantation like this?
|
||||
assert isinstance(inp.type3.application.constructor, TypeConstructor_Tuple)
|
||||
|
||||
args = inp.type3.application.arguments
|
||||
alloc_size = calculate_alloc_size(inp.type3, is_member=False)
|
||||
elif isinstance(inp.type3.application, TypeApplication_TypeInt):
|
||||
# Possibly paranoid assert. If we have a future type of kind * -> Int -> *,
|
||||
# does it also do this tuple instantation like this?
|
||||
@ -138,7 +123,6 @@ def tuple_instantiation(wgn: WasmGenerator, mod: ourlang.Module, inp: ourlang.Tu
|
||||
sa_type, sa_len = inp.type3.application.arguments
|
||||
|
||||
args = tuple(sa_type for _ in range(sa_len.value))
|
||||
alloc_size = calculate_alloc_size(inp.type3, is_member=False)
|
||||
else:
|
||||
raise NotImplementedError('tuple_instantiation', inp.type3)
|
||||
|
||||
@ -151,17 +135,12 @@ def tuple_instantiation(wgn: WasmGenerator, mod: ourlang.Module, inp: ourlang.Tu
|
||||
wgn.add_statement('nop', comment=f'{tmp_var.name} := ({comment_elements})')
|
||||
|
||||
# Allocated the required amounts of bytes in memory
|
||||
wgn.i32.const(alloc_size)
|
||||
wgn.i32.const(calculate_alloc_size(inp.type3, is_member=False))
|
||||
wgn.call(stdlib_alloc.__alloc__)
|
||||
wgn.local.set(tmp_var)
|
||||
|
||||
if alloc_size_header is not None:
|
||||
wgn.local.get(tmp_var)
|
||||
wgn.i32.const(alloc_size_header)
|
||||
wgn.i32.store()
|
||||
|
||||
# Store each element individually
|
||||
offset = 0 if alloc_size_header is None else 4
|
||||
offset = 0
|
||||
for element, exp_type3 in zip(inp.elements, args, strict=True):
|
||||
assert element.type3 == exp_type3
|
||||
|
||||
|
||||
@ -270,9 +270,6 @@ class FunctionParam:
|
||||
self.name = name
|
||||
self.type3 = type3
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'FunctionParam({self.name!r}, {self.type3!r})'
|
||||
|
||||
class Function:
|
||||
"""
|
||||
A function processes input and produces output
|
||||
|
||||
@ -632,15 +632,8 @@ class OurVisitor:
|
||||
|
||||
if isinstance(node.slice, ast.Slice):
|
||||
_raise_static_error(node, 'Must subscript using an index')
|
||||
|
||||
if not isinstance(node.slice, ast.Constant):
|
||||
_raise_static_error(node, 'Must subscript using a constant index')
|
||||
|
||||
if node.slice.value is Ellipsis:
|
||||
return prelude.dynamic_array(
|
||||
self.visit_type(module, node.value),
|
||||
)
|
||||
|
||||
if not isinstance(node.slice.value, int):
|
||||
_raise_static_error(node, 'Must subscript using a constant integer index')
|
||||
if not isinstance(node.ctx, ast.Load):
|
||||
|
||||
@ -20,7 +20,6 @@ from ..type3.types import (
|
||||
Type3,
|
||||
TypeApplication_Nullary,
|
||||
TypeConstructor_Base,
|
||||
TypeConstructor_DynamicArray,
|
||||
TypeConstructor_Function,
|
||||
TypeConstructor_StaticArray,
|
||||
TypeConstructor_Struct,
|
||||
@ -159,15 +158,9 @@ f64 = Type3('f64', TypeApplication_Nullary(None, None))
|
||||
A 32-bits IEEE 754 float, of 64 bits width.
|
||||
"""
|
||||
|
||||
def da_on_create(args: tuple[Type3], typ: Type3) -> None:
|
||||
instance_type_class(InternalPassAsPointer, typ)
|
||||
|
||||
dynamic_array = TypeConstructor_DynamicArray('dynamic_array', on_create=da_on_create)
|
||||
bytes_ = Type3('bytes', TypeApplication_Nullary(None, None))
|
||||
"""
|
||||
This is a dynamic length piece of memory.
|
||||
|
||||
It should be applied with two arguments. It has a runtime
|
||||
determined length, and each argument is the same.
|
||||
This is a runtime-determined length piece of memory that can be indexed at runtime.
|
||||
"""
|
||||
|
||||
def sa_on_create(args: tuple[Type3, IntType3], typ: Type3) -> None:
|
||||
@ -175,10 +168,12 @@ def sa_on_create(args: tuple[Type3, IntType3], typ: Type3) -> None:
|
||||
|
||||
static_array = TypeConstructor_StaticArray('static_array', on_create=sa_on_create)
|
||||
"""
|
||||
This is a fixed length piece of memory.
|
||||
A type constructor.
|
||||
|
||||
It should be applied with two arguments. It has a compile time
|
||||
determined length, and each argument is the same.
|
||||
Any static array is a fixed length piece of memory that can be indexed at runtime.
|
||||
|
||||
It should be applied with one argument. It has a runtime-dynamic length
|
||||
of the same type repeated.
|
||||
"""
|
||||
|
||||
def tp_on_create(args: tuple[Type3, ...], typ: Type3) -> None:
|
||||
@ -213,6 +208,20 @@ This is like a tuple, but each argument is named, so that developers
|
||||
can get and set fields by name.
|
||||
"""
|
||||
|
||||
PRELUDE_TYPES: dict[str, Type3] = {
|
||||
'none': none,
|
||||
'bool': bool_,
|
||||
'u8': u8,
|
||||
'u32': u32,
|
||||
'u64': u64,
|
||||
'i8': i8,
|
||||
'i32': i32,
|
||||
'i64': i64,
|
||||
'f32': f32,
|
||||
'f64': f64,
|
||||
'bytes': bytes_,
|
||||
}
|
||||
|
||||
a = TypeVariable('a', TypeVariableApplication_Nullary(None, None))
|
||||
b = TypeVariable('b', TypeVariableApplication_Nullary(None, None))
|
||||
|
||||
@ -223,7 +232,7 @@ InternalPassAsPointer = Type3Class('InternalPassAsPointer', (a, ), methods={}, o
|
||||
Internal type class to keep track which types we pass arounds as a pointer.
|
||||
"""
|
||||
|
||||
# instance_type_class(InternalPassAsPointer, bytes_)
|
||||
instance_type_class(InternalPassAsPointer, bytes_)
|
||||
# instance_type_class(InternalPassAsPointer, static_array)
|
||||
# instance_type_class(InternalPassAsPointer, tuple_)
|
||||
# instance_type_class(InternalPassAsPointer, struct)
|
||||
@ -528,15 +537,12 @@ instance_type_class(Floating, f64, methods={
|
||||
'sqrt': stdtypes.f64_floating_sqrt,
|
||||
})
|
||||
|
||||
Sized_ = Type3Class('Sized', (t, ), methods={
|
||||
'len': [t(a), u32],
|
||||
Sized_ = Type3Class('Sized', (a, ), methods={
|
||||
'len': [a, u32],
|
||||
}, operators={}) # FIXME: Once we get type class families, add [] here
|
||||
|
||||
instance_type_class(Sized_, dynamic_array, methods={
|
||||
'len': stdtypes.dynamic_array_sized_len,
|
||||
})
|
||||
instance_type_class(Sized_, static_array, methods={
|
||||
'len': stdtypes.static_array_sized_len,
|
||||
instance_type_class(Sized_, bytes_, methods={
|
||||
'len': stdtypes.bytes_sized_len,
|
||||
})
|
||||
|
||||
Extendable = Type3Class('Extendable', (a, b, ), methods={
|
||||
@ -587,33 +593,12 @@ Foldable = Type3Class('Foldable', (t, ), methods={
|
||||
'sum': [Constraint_TypeClassInstanceExists(NatNum, (a, ))],
|
||||
})
|
||||
|
||||
instance_type_class(Foldable, dynamic_array, methods={
|
||||
'sum': stdtypes.dynamic_array_sum,
|
||||
'foldl': stdtypes.dynamic_array_foldl,
|
||||
'foldr': stdtypes.dynamic_array_foldr,
|
||||
})
|
||||
instance_type_class(Foldable, static_array, methods={
|
||||
'sum': stdtypes.static_array_sum,
|
||||
'foldl': stdtypes.static_array_foldl,
|
||||
'foldr': stdtypes.static_array_foldr,
|
||||
})
|
||||
|
||||
bytes_ = dynamic_array(u8)
|
||||
|
||||
PRELUDE_TYPES: dict[str, Type3] = {
|
||||
'none': none,
|
||||
'bool': bool_,
|
||||
'u8': u8,
|
||||
'u32': u32,
|
||||
'u64': u64,
|
||||
'i8': i8,
|
||||
'i32': i32,
|
||||
'i64': i64,
|
||||
'f32': f32,
|
||||
'f64': f64,
|
||||
'bytes': bytes_,
|
||||
}
|
||||
|
||||
PRELUDE_TYPE_CLASSES = {
|
||||
'Eq': Eq,
|
||||
'Ord': Ord,
|
||||
|
||||
@ -1008,23 +1008,11 @@ def f64_intnum_neg(g: Generator, tv_map: TypeVariableLookup) -> None:
|
||||
## ###
|
||||
## Class Sized
|
||||
|
||||
def dynamic_array_sized_len(g: Generator, tv_map: TypeVariableLookup) -> None:
|
||||
def bytes_sized_len(g: Generator, tv_map: TypeVariableLookup) -> None:
|
||||
del tv_map
|
||||
# The length is stored in the first 4 bytes
|
||||
g.i32.load()
|
||||
|
||||
def static_array_sized_len(g: Generator, tvl: TypeVariableLookup) -> None:
|
||||
tv_map, tc_map = tvl
|
||||
|
||||
tvn_map = {
|
||||
x.name: y
|
||||
for x, y in tv_map.items()
|
||||
}
|
||||
|
||||
sa_len = tvn_map['a*']
|
||||
assert isinstance(sa_len, IntType3)
|
||||
g.i32.const(sa_len.value)
|
||||
|
||||
## ###
|
||||
## Extendable
|
||||
|
||||
@ -1095,12 +1083,6 @@ def f32_f64_demote(g: Generator, tv_map: TypeVariableLookup) -> None:
|
||||
del tv_map
|
||||
g.f32.demote_f64()
|
||||
|
||||
## ###
|
||||
## Foldable
|
||||
|
||||
def dynamic_array_sum(g: Generator, tvl: TypeVariableLookup) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def static_array_sum(g: Generator, tvl: TypeVariableLookup) -> None:
|
||||
tv_map, tc_map = tvl
|
||||
|
||||
@ -1214,9 +1196,6 @@ def static_array_sum(g: Generator, tvl: TypeVariableLookup) -> None:
|
||||
g.nop(comment=f'Completed sum for {sa_type.name}[{sa_len.value}]')
|
||||
# End result: [sum]
|
||||
|
||||
def dynamic_array_foldl(g: Generator, tvl: TypeVariableLookup) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def static_array_foldl(g: Generator, tvl: TypeVariableLookup) -> None:
|
||||
tv_map, tc_map = tvl
|
||||
|
||||
@ -1332,9 +1311,6 @@ def static_array_foldl(g: Generator, tvl: TypeVariableLookup) -> None:
|
||||
|
||||
# Stack: [b]
|
||||
|
||||
def dynamic_array_foldr(g: Generator, tvl: TypeVariableLookup) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def static_array_foldr(g: Generator, tvl: TypeVariableLookup) -> None:
|
||||
tv_map, tc_map = tvl
|
||||
|
||||
|
||||
@ -15,7 +15,6 @@ from .types import (
|
||||
Type3,
|
||||
TypeApplication_Nullary,
|
||||
TypeApplication_Struct,
|
||||
TypeApplication_Type,
|
||||
TypeApplication_TypeInt,
|
||||
TypeApplication_TypeStar,
|
||||
TypeConstructor_Base,
|
||||
@ -200,13 +199,6 @@ class SameTypeArgumentConstraint(ConstraintBase):
|
||||
# So we can let the MustImplementTypeClassConstraint handle it.
|
||||
return None
|
||||
|
||||
if isinstance(tc_typ.application, TypeApplication_Type):
|
||||
return [SameTypeConstraint(
|
||||
tc_typ.application.arguments[0],
|
||||
self.arg_var,
|
||||
comment=self.comment,
|
||||
)]
|
||||
|
||||
# FIXME: This feels sketchy. Shouldn't the type variable
|
||||
# have the exact same number as arguments?
|
||||
if isinstance(tc_typ.application, TypeApplication_TypeInt):
|
||||
@ -297,14 +289,6 @@ class TupleMatchConstraint(ConstraintBase):
|
||||
self.exp_type = exp_type
|
||||
self.args = list(args)
|
||||
|
||||
def _generate_dynamic_array(self, sa_args: tuple[Type3]) -> CheckResult:
|
||||
sa_type, = sa_args
|
||||
|
||||
return [
|
||||
SameTypeConstraint(arg, sa_type)
|
||||
for arg in self.args
|
||||
]
|
||||
|
||||
def _generate_static_array(self, sa_args: tuple[Type3, IntType3]) -> CheckResult:
|
||||
sa_type, sa_len = sa_args
|
||||
|
||||
@ -326,7 +310,6 @@ class TupleMatchConstraint(ConstraintBase):
|
||||
]
|
||||
|
||||
GENERATE_ROUTER = TypeApplicationRouter['TupleMatchConstraint', CheckResult]()
|
||||
GENERATE_ROUTER.add(prelude.dynamic_array, _generate_dynamic_array)
|
||||
GENERATE_ROUTER.add(prelude.static_array, _generate_static_array)
|
||||
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
|
||||
|
||||
@ -373,7 +356,7 @@ class MustImplementTypeClassConstraint(ConstraintBase):
|
||||
typ_list.append(typ)
|
||||
continue
|
||||
|
||||
if isinstance(typ.application, (TypeApplication_Type, TypeApplication_TypeInt, TypeApplication_TypeStar)):
|
||||
if isinstance(typ.application, (TypeApplication_TypeInt, TypeApplication_TypeStar)):
|
||||
typ_list.append(typ.application.constructor)
|
||||
continue
|
||||
|
||||
@ -426,29 +409,6 @@ class LiteralFitsConstraint(ConstraintBase):
|
||||
self.type3 = type3
|
||||
self.literal = literal
|
||||
|
||||
def _generate_dynamic_array(self, da_args: tuple[Type3]) -> CheckResult:
|
||||
if not isinstance(self.literal, ourlang.ConstantTuple):
|
||||
return Error('Must be tuple', comment=self.comment)
|
||||
|
||||
da_type, = da_args
|
||||
|
||||
res: list[ConstraintBase] = []
|
||||
|
||||
res.extend(
|
||||
LiteralFitsConstraint(da_type, y)
|
||||
for y in self.literal.value
|
||||
)
|
||||
|
||||
# Generate placeholders so each Literal expression
|
||||
# gets updated when we figure out the type of the
|
||||
# expression the literal is used in
|
||||
res.extend(
|
||||
SameTypeConstraint(da_type, PlaceholderForType([y]))
|
||||
for y in self.literal.value
|
||||
)
|
||||
|
||||
return res
|
||||
|
||||
def _generate_static_array(self, sa_args: tuple[Type3, IntType3]) -> CheckResult:
|
||||
if not isinstance(self.literal, ourlang.ConstantTuple):
|
||||
return Error('Must be tuple', comment=self.comment)
|
||||
@ -530,7 +490,6 @@ class LiteralFitsConstraint(ConstraintBase):
|
||||
return res
|
||||
|
||||
GENERATE_ROUTER = TypeApplicationRouter['LiteralFitsConstraint', CheckResult]()
|
||||
GENERATE_ROUTER.add(prelude.dynamic_array, _generate_dynamic_array)
|
||||
GENERATE_ROUTER.add(prelude.static_array, _generate_static_array)
|
||||
GENERATE_ROUTER.add(prelude.struct, _generate_struct)
|
||||
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
|
||||
|
||||
@ -176,10 +176,7 @@ def _expression_function_call(
|
||||
if not isinstance(sig_arg.application, TypeVariableApplication_Unary):
|
||||
raise NotImplementedError(sig_arg.application)
|
||||
|
||||
if sig_arg.application.arguments not in type_var_map:
|
||||
# e.g., len :: t a -> u32
|
||||
# i.e. "a" does not matter at all
|
||||
continue
|
||||
assert sig_arg.application.arguments in type_var_map # When does this happen?
|
||||
|
||||
yield SameTypeArgumentConstraint(
|
||||
type_var_map[sig_arg],
|
||||
|
||||
@ -7,13 +7,7 @@ from .functions import (
|
||||
TypeVariableApplication_Unary,
|
||||
)
|
||||
from .typeclasses import Type3ClassArgs
|
||||
from .types import (
|
||||
KindArgument,
|
||||
Type3,
|
||||
TypeApplication_Type,
|
||||
TypeApplication_TypeInt,
|
||||
TypeConstructor_Base,
|
||||
)
|
||||
from .types import KindArgument, Type3, TypeApplication_TypeInt, TypeConstructor_Base
|
||||
|
||||
|
||||
class NoRouteForTypeException(Exception):
|
||||
@ -116,12 +110,6 @@ class TypeClassArgsRouter[S, R]:
|
||||
arguments[1][tc_arg] = typ.application.constructor
|
||||
|
||||
if isinstance(tvar.application, TypeVariableApplication_Unary):
|
||||
if isinstance(typ.application, TypeApplication_Type):
|
||||
da_type, = typ.application.arguments
|
||||
sa_type_tv = tvar.application.arguments
|
||||
arguments[0][sa_type_tv] = da_type
|
||||
continue
|
||||
|
||||
# FIXME: This feels sketchy. Shouldn't the type variable
|
||||
# have the exact same number as arguments?
|
||||
if isinstance(typ.application, TypeApplication_TypeInt):
|
||||
|
||||
@ -195,26 +195,6 @@ class TypeConstructor_Base[T]:
|
||||
def __repr__(self) -> str:
|
||||
return f'{self.__class__.__name__}({self.name!r}, ...)'
|
||||
|
||||
class TypeConstructor_Type(TypeConstructor_Base[Tuple[Type3]]):
|
||||
"""
|
||||
Base class type constructors of kind: * -> *
|
||||
|
||||
Notably, static array.
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
def make_application(self, key: Tuple[Type3]) -> 'TypeApplication_Type':
|
||||
return TypeApplication_Type(self, key)
|
||||
|
||||
def make_name(self, key: Tuple[Type3]) -> str:
|
||||
return f'{self.name} {key[0].name} '
|
||||
|
||||
def __call__(self, arg0: Type3) -> Type3:
|
||||
return self.construct((arg0, ))
|
||||
|
||||
class TypeApplication_Type(TypeApplication_Base[TypeConstructor_Type, Tuple[Type3]]):
|
||||
pass
|
||||
|
||||
class TypeConstructor_TypeInt(TypeConstructor_Base[Tuple[Type3, IntType3]]):
|
||||
"""
|
||||
Base class type constructors of kind: * -> Int -> *
|
||||
@ -251,13 +231,6 @@ class TypeConstructor_TypeStar(TypeConstructor_Base[Tuple[Type3, ...]]):
|
||||
class TypeApplication_TypeStar(TypeApplication_Base[TypeConstructor_TypeStar, Tuple[Type3, ...]]):
|
||||
pass
|
||||
|
||||
class TypeConstructor_DynamicArray(TypeConstructor_Type):
|
||||
def make_name(self, key: Tuple[Type3]) -> str:
|
||||
if 'u8' == key[0].name:
|
||||
return 'bytes'
|
||||
|
||||
return f'{key[0].name}[...]'
|
||||
|
||||
class TypeConstructor_StaticArray(TypeConstructor_TypeInt):
|
||||
def make_name(self, key: Tuple[Type3, IntType3]) -> str:
|
||||
return f'{key[0].name}[{key[1].value}]'
|
||||
|
||||
@ -152,25 +152,6 @@ def _allocate_memory_stored_bytes(attrs: tuple[runners.RunnerBase, bytes]) -> in
|
||||
runner.interpreter_write_memory(adr + 4, val)
|
||||
return adr
|
||||
|
||||
def _allocate_memory_stored_dynamic_array(attrs: tuple[runners.RunnerBase, Any], da_args: tuple[type3types.Type3]) -> int:
|
||||
runner, val = attrs
|
||||
|
||||
da_type, = da_args
|
||||
|
||||
if not isinstance(val, tuple):
|
||||
raise InvalidArgumentException(f'Expected tuple; got {val!r} instead')
|
||||
|
||||
alloc_size = 4 + len(val) * calculate_alloc_size(da_type, True)
|
||||
adr = runner.call('stdlib.alloc.__alloc__', alloc_size)
|
||||
assert isinstance(adr, int) # Type int
|
||||
sys.stderr.write(f'Allocation 0x{adr:08x} {repr(val)}\n')
|
||||
|
||||
offset = adr
|
||||
offset += _write_memory_stored_value(runner, offset, prelude.u32, len(val))
|
||||
for val_el_val in val:
|
||||
offset += _write_memory_stored_value(runner, offset, da_type, val_el_val)
|
||||
return adr
|
||||
|
||||
def _allocate_memory_stored_static_array(attrs: tuple[runners.RunnerBase, Any], sa_args: tuple[type3types.Type3, type3types.IntType3]) -> int:
|
||||
runner, val = attrs
|
||||
|
||||
@ -230,7 +211,6 @@ def _allocate_memory_stored_tuple(attrs: tuple[runners.RunnerBase, Any], tp_args
|
||||
|
||||
ALLOCATE_MEMORY_STORED_ROUTER = TypeApplicationRouter[tuple[runners.RunnerBase, Any], Any]()
|
||||
ALLOCATE_MEMORY_STORED_ROUTER.add_n(prelude.bytes_, _allocate_memory_stored_bytes)
|
||||
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.dynamic_array, _allocate_memory_stored_dynamic_array)
|
||||
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.static_array, _allocate_memory_stored_static_array)
|
||||
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.struct, _allocate_memory_stored_struct)
|
||||
ALLOCATE_MEMORY_STORED_ROUTER.add(prelude.tuple_, _allocate_memory_stored_tuple)
|
||||
@ -345,26 +325,6 @@ def _split_read_bytes(all_bytes: bytes, split_sizes: Iterable[int]) -> Generator
|
||||
yield all_bytes[offset:offset + size]
|
||||
offset += size
|
||||
|
||||
def _load_dynamic_array_from_address(attrs: tuple[runners.RunnerBase, int], da_args: tuple[type3types.Type3]) -> Any:
|
||||
runner, adr = attrs
|
||||
da_type, = da_args
|
||||
|
||||
sys.stderr.write(f'Reading 0x{adr:08x} {da_type:s}[...]\n')
|
||||
|
||||
read_bytes = runner.interpreter_read_memory(adr, 4)
|
||||
array_len, = struct.unpack('<I', read_bytes)
|
||||
adr += 4
|
||||
|
||||
arg_size_1 = calculate_alloc_size(da_type, is_member=True)
|
||||
arg_sizes = [arg_size_1 for _ in range(array_len)] # _split_read_bytes requires one arg per value
|
||||
|
||||
read_bytes = runner.interpreter_read_memory(adr, sum(arg_sizes))
|
||||
|
||||
return tuple(
|
||||
_unpack(runner, da_type, arg_bytes)
|
||||
for arg_bytes in _split_read_bytes(read_bytes, arg_sizes)
|
||||
)
|
||||
|
||||
def _load_static_array_from_address(attrs: tuple[runners.RunnerBase, int], sa_args: tuple[type3types.Type3, type3types.IntType3]) -> Any:
|
||||
runner, adr = attrs
|
||||
sub_typ, len_typ = sa_args
|
||||
@ -419,7 +379,6 @@ def _load_tuple_from_address(attrs: tuple[runners.RunnerBase, int], tp_args: tup
|
||||
|
||||
LOAD_FROM_ADDRESS_ROUTER = TypeApplicationRouter[tuple[runners.RunnerBase, int], Any]()
|
||||
LOAD_FROM_ADDRESS_ROUTER.add_n(prelude.bytes_, _load_bytes_from_address)
|
||||
LOAD_FROM_ADDRESS_ROUTER.add(prelude.dynamic_array, _load_dynamic_array_from_address)
|
||||
LOAD_FROM_ADDRESS_ROUTER.add(prelude.static_array, _load_static_array_from_address)
|
||||
LOAD_FROM_ADDRESS_ROUTER.add(prelude.struct, _load_struct_from_address)
|
||||
LOAD_FROM_ADDRESS_ROUTER.add(prelude.tuple_, _load_tuple_from_address)
|
||||
|
||||
@ -60,7 +60,7 @@ CONSTANT: (u32, ) = $VAL0
|
||||
```
|
||||
|
||||
```py
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('dynamic_array_'):
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_'):
|
||||
expect_type_error(
|
||||
'Tuple element count mismatch',
|
||||
'The given literal must fit the expected type',
|
||||
@ -113,7 +113,7 @@ def testEntry() -> i32:
|
||||
```
|
||||
|
||||
```py
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('dynamic_array_'):
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_'):
|
||||
expect_type_error(
|
||||
'Mismatch between applied types argument count',
|
||||
'The type of a tuple is a combination of its members',
|
||||
@ -175,7 +175,7 @@ def testEntry() -> i32:
|
||||
```
|
||||
|
||||
```py
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('dynamic_array_') or TYPE_NAME.startswith('struct_'):
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('struct_'):
|
||||
expect_type_error(
|
||||
TYPE + ' must be (u32, ) instead',
|
||||
'The type of the value returned from function constant should match its return type',
|
||||
@ -226,7 +226,7 @@ def select(x: $TYPE) -> (u32, ):
|
||||
```
|
||||
|
||||
```py
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('dynamic_array_') or TYPE_NAME.startswith('struct_'):
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('struct_'):
|
||||
expect_type_error(
|
||||
TYPE + ' must be (u32, ) instead',
|
||||
'The type of the value returned from function select should match its return type',
|
||||
@ -273,7 +273,7 @@ def testEntry() -> i32:
|
||||
```
|
||||
|
||||
```py
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('dynamic_array_'):
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_'):
|
||||
expect_type_error(
|
||||
'Mismatch between applied types argument count',
|
||||
# FIXME: Shouldn't this be the same as for the else statement?
|
||||
@ -330,7 +330,7 @@ def testEntry() -> i32:
|
||||
```
|
||||
|
||||
```py
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('dynamic_array_') or TYPE_NAME.startswith('struct_'):
|
||||
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('struct_'):
|
||||
expect_type_error(
|
||||
TYPE + ' must be (u32, ) instead',
|
||||
'The type of the value passed to argument 0 of function helper should match the type of that argument',
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
{
|
||||
"TYPE_NAME": "dynamic_array_u64",
|
||||
"TYPE": "u64[...]",
|
||||
"VAL0": "(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, )"
|
||||
}
|
||||
@ -6,7 +6,7 @@ from ..helpers import Suite
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_, in_put, exp_result', [
|
||||
('bytes', b'Hello, world!', 13),
|
||||
('u8[4]', (1, 2, 3, 4), 4),
|
||||
# ('u8[4]', (1, 2, 3, 4), 4), # FIXME: Implement this
|
||||
])
|
||||
def test_len(type_, in_put, exp_result):
|
||||
code_py = f"""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user