def compare(self): left = Expr.parse_value_expr(self.expr.left, self.context) right = Expr.parse_value_expr(self.expr.right, self.context) if right.value is None: raise InvalidLiteral( 'Comparison to None is not allowed, compare against a default value.', self.expr, ) if isinstance(left.typ, ByteArrayLike) and isinstance( right.typ, ByteArrayLike): # TODO: Can this if branch be removed ^ pass elif isinstance(self.expr.op, vy_ast.In) and isinstance( right.typ, ListType): if left.typ != right.typ.subtype: raise TypeMismatch( "Can't use IN comparison with different types!", self.expr, ) return self.build_in_comparator() if isinstance(self.expr.op, vy_ast.Gt): op = 'sgt' elif isinstance(self.expr.op, vy_ast.GtE): op = 'sge' elif isinstance(self.expr.op, vy_ast.LtE): op = 'sle' elif isinstance(self.expr.op, vy_ast.Lt): op = 'slt' elif isinstance(self.expr.op, vy_ast.Eq): op = 'eq' elif isinstance(self.expr.op, vy_ast.NotEq): op = 'ne' else: raise Exception("Unsupported comparison operator") # Compare (limited to 32) byte arrays. if isinstance(left.typ, ByteArrayLike) and isinstance( right.typ, ByteArrayLike): left = Expr(self.expr.left, self.context).lll_node right = Expr(self.expr.right, self.context).lll_node length_mismatch = (left.typ.maxlen != right.typ.maxlen) left_over_32 = left.typ.maxlen > 32 right_over_32 = right.typ.maxlen > 32 if length_mismatch or left_over_32 or right_over_32: left_keccak = keccak256_helper(self.expr, [left], None, self.context) right_keccak = keccak256_helper(self.expr, [right], None, self.context) if op == 'eq' or op == 'ne': return LLLnode.from_list( [op, left_keccak, right_keccak], typ='bool', pos=getpos(self.expr), ) else: raise StructureException( "Can only compare strings/bytes of length shorter", " than 32 bytes other than equality comparisons", self.expr, ) else: def load_bytearray(side): if side.location == 'memory': return ['mload', ['add', 32, side]] elif side.location == 'storage': return ['sload', ['add', 1, ['sha3_32', side]]] return LLLnode.from_list( [op, load_bytearray(left), load_bytearray(right)], typ='bool', pos=getpos(self.expr), ) # Compare other types. if not is_numeric_type(left.typ) or not is_numeric_type(right.typ): if op not in ('eq', 'ne'): raise TypeMismatch("Invalid type for comparison op", self.expr) left_type, right_type = left.typ.typ, right.typ.typ # Special Case: comparison of a literal integer. If in valid range allow it to be compared. if {left_type, right_type} == {'int128', 'uint256'} and { left.typ.is_literal, right.typ.is_literal } == {True, False}: # noqa: E501 comparison_allowed = False if left.typ.is_literal and SizeLimits.in_bounds( right_type, left.value): comparison_allowed = True elif right.typ.is_literal and SizeLimits.in_bounds( left_type, right.value): comparison_allowed = True op = self._signed_to_unsigned_comparision_op(op) if comparison_allowed: return LLLnode.from_list([op, left, right], typ='bool', pos=getpos(self.expr)) elif {left_type, right_type} == {'uint256', 'uint256'}: op = self._signed_to_unsigned_comparision_op(op) elif (left_type in ('decimal', 'int128') or right_type in ('decimal', 'int128')) and left_type != right_type: # noqa: E501 raise TypeMismatch( f'Implicit conversion from {left_type} to {right_type} disallowed, please convert.', self.expr, ) if left_type == right_type: return LLLnode.from_list([op, left, right], typ='bool', pos=getpos(self.expr)) else: raise TypeMismatch( f"Unsupported types for comparison: {left_type} {right_type}", self.expr, )
def parse_Compare(self): left = Expr.parse_value_expr(self.expr.left, self.context) right = Expr.parse_value_expr(self.expr.right, self.context) if right.value is None: return if isinstance(left.typ, ByteArrayLike) and isinstance( right.typ, ByteArrayLike): # TODO: Can this if branch be removed ^ pass elif isinstance(self.expr.op, (vy_ast.In, vy_ast.NotIn)) and isinstance( right.typ, ListType): return self.build_in_comparator() if isinstance(self.expr.op, vy_ast.Gt): op = "sgt" elif isinstance(self.expr.op, vy_ast.GtE): op = "sge" elif isinstance(self.expr.op, vy_ast.LtE): op = "sle" elif isinstance(self.expr.op, vy_ast.Lt): op = "slt" elif isinstance(self.expr.op, vy_ast.Eq): op = "eq" elif isinstance(self.expr.op, vy_ast.NotEq): op = "ne" else: return # Compare (limited to 32) byte arrays. if isinstance(left.typ, ByteArrayLike) and isinstance( right.typ, ByteArrayLike): left = Expr(self.expr.left, self.context).lll_node right = Expr(self.expr.right, self.context).lll_node length_mismatch = left.typ.maxlen != right.typ.maxlen left_over_32 = left.typ.maxlen > 32 right_over_32 = right.typ.maxlen > 32 if length_mismatch or left_over_32 or right_over_32: left_keccak = keccak256_helper(self.expr, [left], None, self.context) right_keccak = keccak256_helper(self.expr, [right], None, self.context) if op == "eq" or op == "ne": return LLLnode.from_list( [op, left_keccak, right_keccak], typ="bool", pos=getpos(self.expr), ) else: return else: def load_bytearray(side): if side.location == "memory": return ["mload", ["add", 32, side]] elif side.location == "storage": return ["sload", ["add", 1, side]] return LLLnode.from_list( [op, load_bytearray(left), load_bytearray(right)], typ="bool", pos=getpos(self.expr), ) # Compare other types. if is_numeric_type(left.typ) and is_numeric_type(right.typ): if left.typ.typ == right.typ.typ == "uint256": # this works because we only have one unsigned integer type # in the future if others are added, this logic must be expanded op = self._signed_to_unsigned_comparision_op(op) elif op not in ("eq", "ne"): return return LLLnode.from_list([op, left, right], typ="bool", pos=getpos(self.expr))
def parse_Compare(self): left = Expr.parse_value_expr(self.expr.left, self.context) right = Expr.parse_value_expr(self.expr.right, self.context) if right.value is None: return if isinstance(left.typ, ByteArrayLike) and isinstance( right.typ, ByteArrayLike): # TODO: Can this if branch be removed ^ pass elif isinstance(self.expr.op, vy_ast.In) and isinstance( right.typ, ListType): if left.typ != right.typ.subtype: return return self.build_in_comparator() if isinstance(self.expr.op, vy_ast.Gt): op = "sgt" elif isinstance(self.expr.op, vy_ast.GtE): op = "sge" elif isinstance(self.expr.op, vy_ast.LtE): op = "sle" elif isinstance(self.expr.op, vy_ast.Lt): op = "slt" elif isinstance(self.expr.op, vy_ast.Eq): op = "eq" elif isinstance(self.expr.op, vy_ast.NotEq): op = "ne" else: return # Compare (limited to 32) byte arrays. if isinstance(left.typ, ByteArrayLike) and isinstance( right.typ, ByteArrayLike): left = Expr(self.expr.left, self.context).lll_node right = Expr(self.expr.right, self.context).lll_node length_mismatch = left.typ.maxlen != right.typ.maxlen left_over_32 = left.typ.maxlen > 32 right_over_32 = right.typ.maxlen > 32 if length_mismatch or left_over_32 or right_over_32: left_keccak = keccak256_helper(self.expr, [left], None, self.context) right_keccak = keccak256_helper(self.expr, [right], None, self.context) if op == "eq" or op == "ne": return LLLnode.from_list( [op, left_keccak, right_keccak], typ="bool", pos=getpos(self.expr), ) else: return else: def load_bytearray(side): if side.location == "memory": return ["mload", ["add", 32, side]] elif side.location == "storage": return ["sload", ["add", 1, ["sha3_32", side]]] return LLLnode.from_list( [op, load_bytearray(left), load_bytearray(right)], typ="bool", pos=getpos(self.expr), ) # Compare other types. if not is_numeric_type(left.typ) or not is_numeric_type(right.typ): if op not in ("eq", "ne"): return left_type, right_type = left.typ.typ, right.typ.typ # Special Case: comparison of a literal integer. If in valid range allow it to be compared. if {left_type, right_type} == {"int128", "uint256"} and { left.typ.is_literal, right.typ.is_literal, } == { True, False, }: # noqa: E501 comparison_allowed = False if left.typ.is_literal and SizeLimits.in_bounds( right_type, left.value): comparison_allowed = True elif right.typ.is_literal and SizeLimits.in_bounds( left_type, right.value): comparison_allowed = True op = self._signed_to_unsigned_comparision_op(op) if comparison_allowed: return LLLnode.from_list([op, left, right], typ="bool", pos=getpos(self.expr)) elif {left_type, right_type} == {"uint256", "uint256"}: op = self._signed_to_unsigned_comparision_op(op) elif (left_type in ("decimal", "int128") or right_type in ("decimal", "int128")) and left_type != right_type: # noqa: E501 return if left_type == right_type: return LLLnode.from_list([op, left, right], typ="bool", pos=getpos(self.expr))
def build_LLL(self, expr, args, kwargs, context): return keccak256_helper(expr, args, kwargs, context)
def _keccak256(expr, args, kwargs, context): return keccak256_helper(expr, args, kwargs, context)