Cleanup CanBeSubscriptedConstraint
It was using an AST argument, and I'd rather not have those in the typing system (except the generator).
This commit is contained in:
parent
df5c1911bf
commit
67af569448
@ -50,7 +50,7 @@ NewConstraintList = List['ConstraintBase']
|
|||||||
|
|
||||||
CheckResult = Union[None, SubstitutionMap, Error, NewConstraintList, RequireTypeSubstitutes]
|
CheckResult = Union[None, SubstitutionMap, Error, NewConstraintList, RequireTypeSubstitutes]
|
||||||
|
|
||||||
HumanReadableRet = Tuple[str, Dict[str, Union[str, ourlang.Expression, Type3, PlaceholderForType]]]
|
HumanReadableRet = Tuple[str, Dict[str, Union[None, int, str, ourlang.Expression, Type3, PlaceholderForType]]]
|
||||||
|
|
||||||
class Context:
|
class Context:
|
||||||
"""
|
"""
|
||||||
@ -500,45 +500,42 @@ class CanBeSubscriptedConstraint(ConstraintBase):
|
|||||||
"""
|
"""
|
||||||
A value that is subscipted, i.e. a[0] (tuple) or a[b] (static array)
|
A value that is subscipted, i.e. a[0] (tuple) or a[b] (static array)
|
||||||
"""
|
"""
|
||||||
__slots__ = ('ret_type3', 'type3', 'index', 'index_phft', )
|
__slots__ = ('ret_type3', 'type3', 'index_type3', 'index_const', )
|
||||||
|
|
||||||
ret_type3: Type3OrPlaceholder
|
ret_type3: PlaceholderForType
|
||||||
type3: Type3OrPlaceholder
|
type3: PlaceholderForType
|
||||||
index: ourlang.Expression
|
index_type3: PlaceholderForType
|
||||||
index_phft: Type3OrPlaceholder
|
index_const: int | None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
ret_type3: PlaceholderForType,
|
ret_type3: PlaceholderForType,
|
||||||
type3: PlaceholderForType,
|
type3: PlaceholderForType,
|
||||||
index: ourlang.Expression,
|
index_type3: PlaceholderForType,
|
||||||
index_phft: PlaceholderForType,
|
index_const: int | None,
|
||||||
comment: Optional[str] = None,
|
comment: Optional[str] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(comment=comment)
|
super().__init__(comment=comment)
|
||||||
|
|
||||||
self.ret_type3 = ret_type3
|
self.ret_type3 = ret_type3
|
||||||
self.type3 = type3
|
self.type3 = type3
|
||||||
self.index = index
|
self.index_type3 = index_type3
|
||||||
self.index_phft = index_phft
|
self.index_const = index_const
|
||||||
|
|
||||||
def _generate_bytes(self) -> CheckResult:
|
def _generate_bytes(self) -> CheckResult:
|
||||||
return [
|
return [
|
||||||
SameTypeConstraint(prelude.u32, self.index_phft, comment='([]) :: bytes -> u32 -> u8'),
|
SameTypeConstraint(prelude.u32, self.index_type3, comment='([]) :: bytes -> u32 -> u8'),
|
||||||
SameTypeConstraint(prelude.u8, self.ret_type3, comment='([]) :: bytes -> u32 -> u8'),
|
SameTypeConstraint(prelude.u8, self.ret_type3, comment='([]) :: bytes -> u32 -> u8'),
|
||||||
]
|
]
|
||||||
|
|
||||||
def _generate_static_array(self, sa_args: tuple[Type3, IntType3]) -> CheckResult:
|
def _generate_static_array(self, sa_args: tuple[Type3, IntType3]) -> CheckResult:
|
||||||
sa_type, sa_len = sa_args
|
sa_type, sa_len = sa_args
|
||||||
|
|
||||||
if isinstance(self.index, ourlang.ConstantPrimitive):
|
if self.index_const is not None and (self.index_const < 0 or sa_len.value <= self.index_const):
|
||||||
assert isinstance(self.index.value, int)
|
|
||||||
|
|
||||||
if self.index.value < 0 or sa_len.value <= self.index.value:
|
|
||||||
return Error('Tuple index out of range')
|
return Error('Tuple index out of range')
|
||||||
|
|
||||||
return [
|
return [
|
||||||
SameTypeConstraint(prelude.u32, self.index_phft, comment='([]) :: Subscriptable a => a b -> u32 -> b'),
|
SameTypeConstraint(prelude.u32, self.index_type3, comment='([]) :: Subscriptable a => a b -> u32 -> b'),
|
||||||
SameTypeConstraint(sa_type, self.ret_type3, comment='([]) :: Subscriptable a => a b -> u32 -> b'),
|
SameTypeConstraint(sa_type, self.ret_type3, comment='([]) :: Subscriptable a => a b -> u32 -> b'),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -547,18 +544,15 @@ class CanBeSubscriptedConstraint(ConstraintBase):
|
|||||||
# e.g. rather than having to do `fst a` and `snd a` and only have to-sized tuples
|
# e.g. rather than having to do `fst a` and `snd a` and only have to-sized tuples
|
||||||
# we use a[0] and a[1] and allow for a[2] and on.
|
# we use a[0] and a[1] and allow for a[2] and on.
|
||||||
|
|
||||||
if not isinstance(self.index, ourlang.ConstantPrimitive):
|
if self.index_const is None:
|
||||||
return Error('Must index with literal')
|
|
||||||
|
|
||||||
if not isinstance(self.index.value, int):
|
|
||||||
return Error('Must index with integer literal')
|
return Error('Must index with integer literal')
|
||||||
|
|
||||||
if self.index.value < 0 or len(tp_args) <= self.index.value:
|
if self.index_const < 0 or len(tp_args) <= self.index_const:
|
||||||
return Error('Tuple index out of range')
|
return Error('Tuple index out of range')
|
||||||
|
|
||||||
return [
|
return [
|
||||||
SameTypeConstraint(prelude.u32, self.index_phft, comment=f'Tuple subscript index {self.index.value}'),
|
SameTypeConstraint(prelude.u32, self.index_type3, comment='([]) :: Subscriptable a => a b -> u32 -> b'),
|
||||||
SameTypeConstraint(tp_args[self.index.value], self.ret_type3, comment=f'Tuple subscript index {self.index.value}'),
|
SameTypeConstraint(tp_args[self.index_const], self.ret_type3, comment=f'Tuple subscript index {self.index_const}'),
|
||||||
]
|
]
|
||||||
|
|
||||||
GENERATE_ROUTER = TypeApplicationRouter['CanBeSubscriptedConstraint', CheckResult]()
|
GENERATE_ROUTER = TypeApplicationRouter['CanBeSubscriptedConstraint', CheckResult]()
|
||||||
@ -567,12 +561,10 @@ class CanBeSubscriptedConstraint(ConstraintBase):
|
|||||||
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
|
GENERATE_ROUTER.add(prelude.tuple_, _generate_tuple)
|
||||||
|
|
||||||
def check(self) -> CheckResult:
|
def check(self) -> CheckResult:
|
||||||
exp_type = self.type3
|
if self.type3.resolve_as is None:
|
||||||
if isinstance(exp_type, PlaceholderForType):
|
|
||||||
if exp_type.resolve_as is None:
|
|
||||||
return RequireTypeSubstitutes()
|
return RequireTypeSubstitutes()
|
||||||
|
|
||||||
exp_type = exp_type.resolve_as
|
exp_type = self.type3.resolve_as
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return self.__class__.GENERATE_ROUTER(self, exp_type)
|
return self.__class__.GENERATE_ROUTER(self, exp_type)
|
||||||
@ -584,9 +576,9 @@ class CanBeSubscriptedConstraint(ConstraintBase):
|
|||||||
'{type3}[{index}]',
|
'{type3}[{index}]',
|
||||||
{
|
{
|
||||||
'type3': self.type3,
|
'type3': self.type3,
|
||||||
'index': self.index,
|
'index': self.index_type3 if self.index_const is None else self.index_const,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f'CanBeSubscriptedConstraint({repr(self.type3)}, {repr(self.index)}, comment={repr(self.comment)})'
|
return f'CanBeSubscriptedConstraint({self.ret_type3!r}, {self.type3!r}, {self.index_type3!r}, {self.index_const!r}, comment={repr(self.comment)})'
|
||||||
|
|||||||
@ -193,7 +193,10 @@ def expression(ctx: Context, inp: ourlang.Expression, phft: PlaceholderForType)
|
|||||||
yield from expression(ctx, inp.varref, varref_phft)
|
yield from expression(ctx, inp.varref, varref_phft)
|
||||||
yield from expression(ctx, inp.index, index_phft)
|
yield from expression(ctx, inp.index, index_phft)
|
||||||
|
|
||||||
yield CanBeSubscriptedConstraint(phft, varref_phft, inp.index, index_phft)
|
if isinstance(inp.index, ourlang.ConstantPrimitive) and isinstance(inp.index.value, int):
|
||||||
|
yield CanBeSubscriptedConstraint(phft, varref_phft, index_phft, inp.index.value)
|
||||||
|
else:
|
||||||
|
yield CanBeSubscriptedConstraint(phft, varref_phft, index_phft, None)
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(inp, ourlang.AccessStructMember):
|
if isinstance(inp, ourlang.AccessStructMember):
|
||||||
|
|||||||
@ -64,7 +64,7 @@ def testEntry(x: (u8, u32, u64), y: u8) -> u64:
|
|||||||
return x[y]
|
return x[y]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with pytest.raises(Type3Exception, match='Must index with literal'):
|
with pytest.raises(Type3Exception, match='Must index with integer literal'):
|
||||||
Suite(code_py).run_code()
|
Suite(code_py).run_code()
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user