diff --git a/src/puya/awst/function_traverser.py b/src/puya/awst/function_traverser.py index 25f83ae8f4..5a8c9f571c 100644 --- a/src/puya/awst/function_traverser.py +++ b/src/puya/awst/function_traverser.py @@ -244,11 +244,6 @@ def visit_bytes_unary_operation(self, expr: awst_nodes.BytesUnaryOperation) -> N def visit_not_expression(self, expr: awst_nodes.Not) -> None: expr.expr.accept(self) - @typing.override - def visit_contains_expression(self, expr: awst_nodes.Contains) -> None: - expr.item.accept(self) - expr.sequence.accept(self) - @typing.override def visit_block(self, statement: awst_nodes.Block) -> None: for stmt in statement.body: diff --git a/src/puya/awst/nodes.py b/src/puya/awst/nodes.py index 6dc95475d0..be944136db 100644 --- a/src/puya/awst/nodes.py +++ b/src/puya/awst/nodes.py @@ -1255,41 +1255,6 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_not_expression(self) -@attrs.frozen -class Contains(Expression): - item: Expression - sequence: Expression - wtype: WType = attrs.field(default=wtypes.bool_wtype, init=False) - - def __attrs_post_init__(self) -> None: - if self.sequence.wtype == wtypes.bytes_wtype: - raise InternalError( - "Use IsSubstring for 'in' or 'not in' checks with Bytes", self.source_location - ) - # TODO: this type handling here probably isn't scalable - if isinstance(self.sequence.wtype, wtypes.WArray): - if self.sequence.wtype.element_type != self.item.wtype: - raise CodeError( - f"array element type {self.sequence.wtype.element_type}" - f" differs from {self.item.wtype}", - self.source_location, - ) - elif isinstance(self.sequence.wtype, wtypes.WTuple): - if self.item.wtype not in self.sequence.wtype.types: - raise CodeError( - f"{self.sequence.wtype} does not have element with type {self.item.wtype}", - self.source_location, - ) - else: - raise CodeError( - f"Type doesn't support in/not in checks: {self.sequence.wtype}", - self.source_location, - ) - - def accept(self, visitor: ExpressionVisitor[T]) -> T: - return visitor.visit_contains_expression(self) - - @attrs.frozen class UInt64AugmentedAssignment(Statement): target: Lvalue = attrs.field(validator=[wtype_is_uint64]) diff --git a/src/puya/awst/to_code_visitor.py b/src/puya/awst/to_code_visitor.py index 923144fc07..ff2162f0a4 100644 --- a/src/puya/awst/to_code_visitor.py +++ b/src/puya/awst/to_code_visitor.py @@ -60,9 +60,6 @@ def visit_arc4_decode(self, expr: nodes.ARC4Decode) -> str: def visit_arc4_encode(self, expr: nodes.ARC4Encode) -> str: return f"arc4_encode({expr.value.accept(self)}, {expr.wtype})" - def visit_contains_expression(self, expr: nodes.Contains) -> str: - return f"{expr.item.accept(self)} IS IN {expr.sequence.accept(self)}" - def visit_reinterpret_cast(self, expr: nodes.ReinterpretCast) -> str: return f"reinterpret_cast<{expr.wtype}>({expr.expr.accept(self)})" diff --git a/src/puya/awst/visitors.py b/src/puya/awst/visitors.py index 8aed9996d3..df963ba259 100644 --- a/src/puya/awst/visitors.py +++ b/src/puya/awst/visitors.py @@ -226,9 +226,6 @@ def visit_bytes_unary_operation(self, expr: puya.awst.nodes.BytesUnaryOperation) @abstractmethod def visit_not_expression(self, expr: puya.awst.nodes.Not) -> T: ... - @abstractmethod - def visit_contains_expression(self, expr: puya.awst.nodes.Contains) -> T: ... - @abstractmethod def visit_reinterpret_cast(self, expr: puya.awst.nodes.ReinterpretCast) -> T: ... diff --git a/src/puya/ir/builder/main.py b/src/puya/ir/builder/main.py index 0205f1d018..97c2c1107f 100644 --- a/src/puya/ir/builder/main.py +++ b/src/puya/ir/builder/main.py @@ -833,54 +833,6 @@ def visit_not_expression(self, expr: awst_nodes.Not) -> TExpression: source_location=expr.source_location, ) - def visit_contains_expression(self, expr: awst_nodes.Contains) -> TExpression: - item_register = self.visit_and_materialise_single(expr.item) - - if not isinstance(expr.sequence.wtype, wtypes.WTuple): - raise InternalError( - f"Containment operation IR lowering" - f" not implemented for sequence type {expr.sequence.wtype.name}", - expr.source_location, - ) - items_sequence = [ - item - for item, item_wtype in zip( - self.visit_and_materialise(expr.sequence), expr.sequence.wtype.types, strict=True - ) - if item_wtype == expr.item.wtype - ] - - condition = None - for item in items_sequence: - equal_i = Intrinsic( - op=get_comparison_op_for_wtype(awst_nodes.NumericComparison.eq, expr.item.wtype), - args=[ - item_register, - item, - ], - source_location=expr.source_location, - ) - if not condition: - condition = equal_i - continue - left_var = assign_temp( - self.context, - source=condition, - temp_description="contains", - source_location=expr.source_location, - ) - right_var = assign_temp( - self.context, - source=equal_i, - temp_description="is_equal", - source_location=expr.source_location, - ) - condition = Intrinsic( - op=AVMOp.or_, args=[left_var, right_var], source_location=expr.source_location - ) - - return condition or UInt64Constant(source_location=expr.source_location, value=0) - def visit_reinterpret_cast(self, expr: awst_nodes.ReinterpretCast) -> TExpression: # should be a no-op for us, but we validate the cast here too source = self.visit_expr(expr.expr)