Skip to main content

kohebi_core/
ops.rs

1//! The operators, and the exact words CPython uses when they do not apply.
2//!
3//! Everything here is a free function over [`Object`] rather than a method,
4//! because an operator in Python is not something a value does on its own. It
5//! is a negotiation between two values, and the error message depends on both.
6//!
7//! There are no user-defined types yet, so there is no `__add__` to call and no
8//! reflected operand to fall back to. What that machinery decides for the
9//! builtin types is written out directly, including which of the two operands
10//! gets to name itself in the message. `1 + 'a'` and `'a' + 1` are both a
11//! `TypeError` and they do not say the same thing, and a program that prints
12//! the message can tell.
13//!
14//! ## What is not here
15//!
16//! A negative base raised to a fractional power is a complex number in Python,
17//! and there is no complex type yet, so [`pow`] reports that rather than
18//! returning a wrong real. `%` on a string is formatting rather than a
19//! remainder, and that is not here either; [`modulo`] gives a `TypeError` for
20//! it today where CPython would format. Both are noted where they happen.
21
22use std::cmp::Ordering;
23use std::rc::Rc;
24
25use num_bigint::BigInt;
26use num_traits::FromPrimitive;
27
28use crate::dict::Set;
29use crate::error::{Error, Kind, Result};
30use crate::hash::Key;
31use crate::int::{DivideByZero, Int};
32use crate::object::Object;
33use crate::slice::Indices;
34use crate::text::{Str, StrBuf};
35
36/// How much a repetition may ask for before it is refused.
37///
38/// CPython's limit is whatever the allocator will hand over, so `'a' * 10**18`
39/// is a `MemoryError` on every machine anyone has and a smaller request might
40/// succeed on one machine and not another. A fixed ceiling gives the same
41/// answer everywhere, and it is a `MemoryError` either way. It is set well past
42/// anything a program means to ask for and well under anything that would take
43/// the process down with it.
44const REPEAT_LIMIT: u64 = 1 << 40;
45
46/// The comparison operators, which are one operator with six spellings.
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub enum Compare {
49    /// `==`
50    Eq,
51    /// `!=`
52    Ne,
53    /// `<`
54    Lt,
55    /// `<=`
56    Le,
57    /// `>`
58    Gt,
59    /// `>=`
60    Ge,
61}
62
63impl Compare {
64    /// How the operator is written, which is what its error message quotes.
65    #[must_use]
66    pub const fn symbol(self) -> &'static str {
67        match self {
68            Compare::Eq => "==",
69            Compare::Ne => "!=",
70            Compare::Lt => "<",
71            Compare::Le => "<=",
72            Compare::Gt => ">",
73            Compare::Ge => ">=",
74        }
75    }
76
77    /// What this operator answers for an ordering that came out somewhere.
78    #[must_use]
79    const fn decide(self, ordering: Ordering) -> bool {
80        match self {
81            Compare::Eq => ordering.is_eq(),
82            Compare::Ne => ordering.is_ne(),
83            Compare::Lt => ordering.is_lt(),
84            Compare::Le => ordering.is_le(),
85            Compare::Gt => ordering.is_gt(),
86            Compare::Ge => ordering.is_ge(),
87        }
88    }
89
90    /// Whether this is one of the two that every pair of objects answers.
91    #[must_use]
92    const fn is_equality(self) -> bool {
93        matches!(self, Compare::Eq | Compare::Ne)
94    }
95}
96
97/// `left + right`.
98///
99/// Numbers add and sequences join, and the two never mix. A `str` and a
100/// `bytes` look alike enough that a program might expect them to concatenate,
101/// and CPython goes out of its way to say they do not.
102pub fn add(left: &Object, right: &Object) -> Result<Object> {
103    if let Some(pair) = promote(left, right)? {
104        return Ok(match pair {
105            Pair::Ints(a, b) => Object::Int(a.add(b)),
106            Pair::Floats(a, b) => Object::Float(a + b),
107        });
108    }
109    match (left, right) {
110        (Object::Str(a), Object::Str(b)) => {
111            let mut buf = StrBuf::new();
112            buf.push_string(a);
113            buf.push_string(b);
114            Ok(Object::Str(Rc::new(buf.finish())))
115        }
116        (Object::Bytes(a), Object::Bytes(b)) => {
117            let mut joined = a.to_vec();
118            joined.extend_from_slice(b);
119            Ok(Object::Bytes(joined.into()))
120        }
121        (Object::Tuple(a), Object::Tuple(b)) => {
122            let mut joined = a.to_vec();
123            joined.extend_from_slice(b);
124            Ok(Object::tuple(joined))
125        }
126        (Object::List(a), Object::List(b)) => {
127            // Both borrows are shared, so `x + x` reads the same list twice
128            // rather than panicking on it.
129            let mut joined = a.borrow().clone();
130            joined.extend(b.borrow().iter().cloned());
131            Ok(Object::list(joined))
132        }
133        _ => Err(concat_error(left, right)),
134    }
135}
136
137/// `left - right`, which is arithmetic on numbers and difference on sets.
138pub fn sub(left: &Object, right: &Object) -> Result<Object> {
139    if let Some(pair) = promote(left, right)? {
140        return Ok(match pair {
141            Pair::Ints(a, b) => Object::Int(a.sub(b)),
142            Pair::Floats(a, b) => Object::Float(a - b),
143        });
144    }
145    if let (Object::Set(a), Object::Set(b)) = (left, right) {
146        let (a, b) = (a.borrow(), b.borrow());
147        return Ok(Object::set(
148            a.iter().filter(|key| !b.contains(key)).cloned().collect(),
149        ));
150    }
151    Err(unsupported("-", left, right))
152}
153
154/// `left * right`, which is arithmetic on numbers and repetition on sequences.
155///
156/// A count is an `int` or a `bool`, and nothing else, however round the float
157/// happens to be. A negative count gives an empty sequence rather than an
158/// error, which is what makes `'-' * (width - len(s))` safe to write.
159pub fn mul(left: &Object, right: &Object) -> Result<Object> {
160    if let Some(pair) = promote(left, right)? {
161        return Ok(match pair {
162            Pair::Ints(a, b) => Object::Int(a.mul(b)),
163            Pair::Floats(a, b) => Object::Float(a * b),
164        });
165    }
166    // The count can be on either side, and whichever side it is not on is the
167    // one that has to be a sequence.
168    let (sequence, count) = match (index(left), index(right)) {
169        (_, Some(count)) => (left, count?),
170        (Some(count), None) => (right, count?),
171        (None, None) => return Err(repeat_error(left, right)),
172    };
173    repeat(sequence, count)?.ok_or_else(|| repeat_error(left, right))
174}
175
176/// `left / right`, which is a float however the operands are spelled.
177pub fn true_div(left: &Object, right: &Object) -> Result<Object> {
178    let Some(pair) = promote(left, right)? else {
179        return Err(unsupported("/", left, right));
180    };
181    match pair {
182        Pair::Ints(a, b) => match a.true_div(b) {
183            Ok(Some(value)) => Ok(Object::Float(value)),
184            Ok(None) => Err(Error::overflow(
185                "integer division result too large for a float",
186            )),
187            Err(DivideByZero) => Err(divide_by_zero()),
188        },
189        Pair::Floats(a, b) => {
190            if b == 0.0 {
191                return Err(divide_by_zero());
192            }
193            Ok(Object::Float(a / b))
194        }
195    }
196}
197
198/// `left // right`, which rounds towards negative infinity rather than towards
199/// zero, so `-7 // 2` is `-4` and not `-3`.
200pub fn floor_div(left: &Object, right: &Object) -> Result<Object> {
201    let Some(pair) = promote(left, right)? else {
202        return Err(unsupported("//", left, right));
203    };
204    match pair {
205        Pair::Ints(a, b) => a
206            .floor_div(b)
207            .map(Object::Int)
208            .map_err(|DivideByZero| divide_by_zero()),
209        Pair::Floats(a, b) => Ok(Object::Float(float_div_mod(a, b)?.0)),
210    }
211}
212
213/// `left % right`.
214///
215/// The result takes the sign of the divisor, which is what keeps
216/// `x % n` inside `range(n)` for a positive `n`.
217///
218/// `'%s' % value` is string formatting rather than a remainder, and there is no
219/// formatter yet, so a `str` on the left gets a `TypeError` here where CPython
220/// would build a string.
221pub fn modulo(left: &Object, right: &Object) -> Result<Object> {
222    let Some(pair) = promote(left, right)? else {
223        return Err(unsupported("%", left, right));
224    };
225    match pair {
226        Pair::Ints(a, b) => a
227            .modulo(b)
228            .map(Object::Int)
229            .map_err(|DivideByZero| divide_by_zero()),
230        Pair::Floats(a, b) => Ok(Object::Float(float_div_mod(a, b)?.1)),
231    }
232}
233
234/// `divmod(left, right)`, which is the quotient and the remainder computed once
235/// rather than the two operators run separately.
236pub fn div_mod(left: &Object, right: &Object) -> Result<Object> {
237    let Some(pair) = promote(left, right)? else {
238        return Err(unsupported("divmod()", left, right));
239    };
240    let (quotient, remainder) = match pair {
241        Pair::Ints(a, b) => {
242            let (q, r) = a.div_mod(b).map_err(|DivideByZero| divide_by_zero())?;
243            (Object::Int(q), Object::Int(r))
244        }
245        Pair::Floats(a, b) => {
246            let (q, r) = float_div_mod(a, b)?;
247            (Object::Float(q), Object::Float(r))
248        }
249    };
250    Ok(Object::tuple(vec![quotient, remainder]))
251}
252
253/// `base ** exponent`.
254///
255/// An integer to a non-negative integer power is an integer, and every other
256/// combination is a float. A negative base to a fractional power is a complex
257/// number in Python, and there is no complex type yet, so that case reports
258/// itself instead of returning the real part on its own.
259pub fn pow(base: &Object, exponent: &Object) -> Result<Object> {
260    let Some(pair) = promote(base, exponent)? else {
261        return Err(unsupported("** or pow()", base, exponent));
262    };
263    match pair {
264        Pair::Ints(a, b) if !b.is_negative() => match a.pow(b) {
265            Some(value) => Ok(Object::Int(value)),
266            // The result is past the ceiling in `Int::pow`. CPython has no
267            // ceiling and would spend the memory, so this arrives sooner than
268            // it does there, as the same exception.
269            None => Err(Error::new(Kind::MemoryError, "")),
270        },
271        // A negative integer exponent leaves the integers, which is why
272        // `2 ** -1` is `0.5` and not `0`.
273        Pair::Ints(a, b) => float_pow(to_float(a)?, to_float(b)?),
274        Pair::Floats(a, b) => float_pow(a, b),
275    }
276}
277
278/// `left << right`.
279pub fn lshift(left: &Object, right: &Object) -> Result<Object> {
280    shift(left, right, "<<", Int::shl)
281}
282
283/// `left >> right`, which is arithmetic, so a negative number shifted far
284/// enough lands on `-1` rather than on zero.
285pub fn rshift(left: &Object, right: &Object) -> Result<Object> {
286    shift(left, right, ">>", Int::shr)
287}
288
289/// `left & right`, which is bitwise on integers and intersection on sets.
290pub fn bit_and(left: &Object, right: &Object) -> Result<Object> {
291    bitwise(left, right, "&", Int::bitand, |a, b| {
292        a.iter().filter(|key| b.contains(key)).cloned().collect()
293    })
294}
295
296/// `left | right`, which is bitwise on integers and union on sets.
297pub fn bit_or(left: &Object, right: &Object) -> Result<Object> {
298    bitwise(left, right, "|", Int::bitor, |a, b| {
299        a.iter().chain(b.iter()).cloned().collect()
300    })
301}
302
303/// `left ^ right`, which is bitwise on integers and symmetric difference on
304/// sets.
305pub fn bit_xor(left: &Object, right: &Object) -> Result<Object> {
306    bitwise(left, right, "^", Int::bitxor, |a, b| {
307        a.iter()
308            .filter(|key| !b.contains(key))
309            .chain(b.iter().filter(|key| !a.contains(key)))
310            .cloned()
311            .collect()
312    })
313}
314
315/// `-value`.
316pub fn neg(value: &Object) -> Result<Object> {
317    match number(value) {
318        Some(Num::Int(value)) => Ok(Object::Int(value.neg())),
319        Some(Num::Float(value)) => Ok(Object::Float(-value)),
320        None => Err(bad_unary("-", value)),
321    }
322}
323
324/// `+value`, which is not a no-op: it turns a `bool` into the `int` it is.
325pub fn pos(value: &Object) -> Result<Object> {
326    match number(value) {
327        Some(Num::Int(value)) => Ok(Object::Int(value.clone())),
328        Some(Num::Float(value)) => Ok(Object::Float(value)),
329        None => Err(bad_unary("+", value)),
330    }
331}
332
333/// `~value`, which is defined on integers and not on floats.
334pub fn invert(value: &Object) -> Result<Object> {
335    match number(value) {
336        Some(Num::Int(value)) => Ok(Object::Int(value.invert())),
337        _ => Err(bad_unary("~", value)),
338    }
339}
340
341/// `abs(value)`.
342///
343/// Here rather than in the builtin that calls it because it is the same
344/// question the unary operators above ask, of the same two number types,
345/// through the same private view of what counts as a number. The only thing
346/// that marks it out is the message, which names the function rather than an
347/// operator because that is what the caller wrote.
348pub fn abs(value: &Object) -> Result<Object> {
349    match number(value) {
350        Some(Num::Int(value)) => Ok(Object::Int(value.abs())),
351        Some(Num::Float(value)) => Ok(Object::Float(value.abs())),
352        None => Err(Error::type_error(format!(
353            "bad operand type for abs(): '{}'",
354            value.type_name()
355        ))),
356    }
357}
358
359/// `not value`, which every object answers because every object has a truth.
360#[must_use]
361pub fn not(value: &Object) -> Object {
362    Object::Bool(!value.truthy())
363}
364
365/// `left <op> right` for the six comparison operators.
366///
367/// `==` and `!=` answer for every pair of objects, and the four orderings only
368/// for pairs that have an order. Note that `==` here is the bare operator,
369/// which is not the same question a container asks about its elements: a NaN is
370/// not equal to itself, and yet `[nan] == [nan]` is true for the same NaN in
371/// both because a container checks identity first.
372pub fn compare(op: Compare, left: &Object, right: &Object) -> Result<Object> {
373    if op.is_equality() {
374        let equal = left.equals(right);
375        return Ok(Object::Bool(equal == (op == Compare::Eq)));
376    }
377    order(op, left, right).map(Object::Bool)
378}
379
380/// `value in container`.
381pub fn contains(container: &Object, value: &Object) -> Result<Object> {
382    let found = match container {
383        Object::Str(text) => {
384            let Object::Str(needle) = value else {
385                return Err(Error::type_error(format!(
386                    "'in <string>' requires string as left operand, not {}",
387                    value.type_name()
388                )));
389            };
390            substring(text, needle)
391        }
392        Object::Bytes(haystack) => match value {
393            Object::Bytes(needle) => subslice(haystack, needle),
394            Object::Int(_) | Object::Bool(_) => {
395                let Some(Num::Int(byte)) = number(value) else {
396                    unreachable!("an int and a bool are both numbers")
397                };
398                let byte = byte
399                    .to_i64()
400                    .and_then(|value| u8::try_from(value).ok())
401                    .ok_or_else(|| Error::value_error("byte must be in range(0, 256)"))?;
402                haystack.contains(&byte)
403            }
404            other => {
405                return Err(Error::type_error(format!(
406                    "a bytes-like object is required, not '{}'",
407                    other.type_name()
408                )));
409            }
410        },
411        Object::Tuple(items) => items.iter().any(|item| item.same_value(value)),
412        Object::List(items) => items.borrow().iter().any(|item| item.same_value(value)),
413        Object::Dict(entries) => entries.borrow().contains(&key(value, "dict key")?),
414        Object::Set(members) => members.borrow().contains(&key(value, "set element")?),
415        other => {
416            return Err(Error::type_error(format!(
417                "argument of type '{}' is not a container or iterable",
418                other.type_name()
419            )));
420        }
421    };
422    Ok(Object::Bool(found))
423}
424
425/// A numeric value with `bool` folded into the `int` it is.
426///
427/// The integer is borrowed rather than owned. An operator only reads its
428/// operands, and owning them meant copying a machine word twice for every
429/// addition in a loop and allocating twice for every addition on a bignum, for
430/// two values thrown away on the next line.
431enum Num<'a> {
432    Int(&'a Int),
433    Float(f64),
434}
435
436/// Two numbers of the same kind, which is what an arithmetic operator wants.
437enum Pair<'a> {
438    Ints(&'a Int, &'a Int),
439    Floats(f64, f64),
440}
441
442/// The two integers a `bool` is, so that [`number`] has something to point at.
443/// A `bool` in Python is an `int`, and these are the two it can be.
444static FALSE: Int = Int::Small(0);
445static TRUE: Int = Int::Small(1);
446
447/// This value seen as a number, if it is one.
448fn number(value: &Object) -> Option<Num<'_>> {
449    match value {
450        Object::Bool(true) => Some(Num::Int(&TRUE)),
451        Object::Bool(false) => Some(Num::Int(&FALSE)),
452        Object::Int(value) => Some(Num::Int(value)),
453        Object::Float(value) => Some(Num::Float(*value)),
454        _ => None,
455    }
456}
457
458/// Both operands as numbers of one kind, or `None` if either is not a number.
459///
460/// Mixing an int with a float converts the int, and an int with more than about
461/// three hundred digits has no float to convert to. CPython reports that rather
462/// than rounding to infinity, which is why this returns a `Result` at all.
463fn promote<'a>(left: &'a Object, right: &'a Object) -> Result<Option<Pair<'a>>> {
464    let (Some(left), Some(right)) = (number(left), number(right)) else {
465        return Ok(None);
466    };
467    Ok(Some(match (left, right) {
468        (Num::Int(a), Num::Int(b)) => Pair::Ints(a, b),
469        (Num::Float(a), Num::Float(b)) => Pair::Floats(a, b),
470        (Num::Int(a), Num::Float(b)) => Pair::Floats(to_float(a)?, b),
471        (Num::Float(a), Num::Int(b)) => Pair::Floats(a, to_float(b)?),
472    }))
473}
474
475/// An integer as a float, or the exception CPython raises when there is none.
476fn to_float(value: &Int) -> Result<f64> {
477    value
478        .to_f64()
479        .ok_or_else(|| Error::overflow("int too large to convert to float"))
480}
481
482/// `x ** y` on two floats, including the two cases that are not a float at all.
483fn float_pow(base: f64, exponent: f64) -> Result<Object> {
484    if base == 0.0 && exponent < 0.0 {
485        return Err(Error::zero_division("zero to a negative power"));
486    }
487    if base < 0.0 && exponent.is_finite() && exponent.fract() != 0.0 {
488        return Err(Error::new(
489            Kind::NotImplementedError,
490            "a negative number raised to a fractional power is a complex number, \
491             and complex numbers are not implemented yet",
492        ));
493    }
494    let value = base.powf(exponent);
495    if value.is_infinite() && base.is_finite() && exponent.is_finite() {
496        // What the C library reports through `errno` as `ERANGE`, which CPython
497        // passes on with the number and the text the platform gave it.
498        return Err(Error::overflow("(34, 'Result too large')"));
499    }
500    Ok(Object::Float(value))
501}
502
503/// `x // y` and `x % y` on two floats, computed together because each is a
504/// correction of the other.
505///
506/// This is CPython's `float_divmod`, and the corrections are not decoration.
507/// `fmod` takes the sign of the dividend and Python's `%` takes the sign of the
508/// divisor, so `-5.5 % 2.0` is `0.5` here and `-1.5` in C.
509fn float_div_mod(left: f64, right: f64) -> Result<(f64, f64)> {
510    if right == 0.0 {
511        return Err(divide_by_zero());
512    }
513    let mut remainder = left % right;
514    let mut quotient = (left - remainder) / right;
515    if remainder == 0.0 {
516        // A zero remainder still has a sign, and it is the divisor's.
517        remainder = 0.0_f64.copysign(right);
518    } else if (right < 0.0) != (remainder < 0.0) {
519        remainder += right;
520        quotient -= 1.0;
521    }
522    let quotient = if quotient == 0.0 {
523        0.0_f64.copysign(left / right)
524    } else {
525        let floor = quotient.floor();
526        // The division above loses the low bits when the quotient is large, and
527        // half a unit is where that shows. Snapping it back is what CPython
528        // does and it is the difference between `7.0 // 0.5` being 14 and 13.
529        if quotient - floor > 0.5 {
530            floor + 1.0
531        } else {
532            floor
533        }
534    };
535    Ok((quotient, remainder))
536}
537
538/// One of the two shifts, which differ only in which way they go.
539fn shift(
540    left: &Object,
541    right: &Object,
542    symbol: &str,
543    apply: impl Fn(&Int, &Int) -> Option<Int>,
544) -> Result<Object> {
545    let (Some(Num::Int(a)), Some(Num::Int(b))) = (number(left), number(right)) else {
546        return Err(unsupported(symbol, left, right));
547    };
548    if b.is_negative() {
549        return Err(Error::value_error("negative shift count"));
550    }
551    match apply(a, b) {
552        Some(value) => Ok(Object::Int(value)),
553        None => Err(Error::new(Kind::MemoryError, "")),
554    }
555}
556
557/// One of the three bitwise operators, each of which is also a set operator.
558fn bitwise(
559    left: &Object,
560    right: &Object,
561    symbol: &str,
562    on_ints: impl Fn(&Int, &Int) -> Int,
563    on_sets: impl Fn(&Set, &Set) -> Set,
564) -> Result<Object> {
565    if let (Some(Num::Int(a)), Some(Num::Int(b))) = (number(left), number(right)) {
566        let value = on_ints(a, b);
567        // Two bools give a bool, which is the one place a bitwise operator does
568        // not widen to `int`. `True & True` is `True` and `True + True` is `2`.
569        if matches!((left, right), (Object::Bool(_), Object::Bool(_))) {
570            return Ok(Object::Bool(!value.is_zero()));
571        }
572        return Ok(Object::Int(value));
573    }
574    if let (Object::Set(a), Object::Set(b)) = (left, right) {
575        let (a, b) = (a.borrow(), b.borrow());
576        return Ok(Object::set(on_sets(&a, &b)));
577    }
578    Err(unsupported(symbol, left, right))
579}
580
581/// This value as a repetition count, if it is one that Python would accept.
582///
583/// The outer `Option` is whether it is an integer at all, and the inner
584/// `Result` is whether the integer is one a machine can count to. They are
585/// different answers: the first sends the caller off to look at the other
586/// operand, and the second is an exception.
587fn index(value: &Object) -> Option<Result<usize>> {
588    let count = match number(value)? {
589        Num::Int(count) => count,
590        Num::Float(_) => return None,
591    };
592    // A negative count is an empty sequence rather than an error, which is what
593    // makes padding to a width that has already been passed harmless.
594    if count.is_negative() {
595        return Some(Ok(0));
596    }
597    // An index in CPython is a signed word, so the top half of the unsigned
598    // range is out even though a `usize` would hold it.
599    Some(
600        count
601            .to_usize()
602            .filter(|count| isize::try_from(*count).is_ok())
603            .ok_or_else(|| Error::overflow("cannot fit 'int' into an index-sized integer")),
604    )
605}
606
607/// `value * count` for a sequence, or `None` if it is not a sequence.
608fn repeat(value: &Object, count: usize) -> Result<Option<Object>> {
609    let repeated = match value {
610        Object::Str(text) => {
611            let points: Vec<u32> = text.code_points().collect();
612            room(points.len(), count, size_of::<char>())?;
613            let mut buf = StrBuf::new();
614            for _ in 0..count {
615                for point in &points {
616                    buf.push_code_point(*point);
617                }
618            }
619            Object::Str(Rc::new(buf.finish()))
620        }
621        Object::Bytes(bytes) => {
622            room(bytes.len(), count, 1)?;
623            Object::Bytes(bytes.repeat(count).into())
624        }
625        Object::Tuple(items) => {
626            room(items.len(), count, size_of::<Object>())?;
627            Object::tuple(repeated_elements(items, count))
628        }
629        Object::List(items) => {
630            let items = items.borrow();
631            room(items.len(), count, size_of::<Object>())?;
632            Object::list(repeated_elements(&items, count))
633        }
634        _ => return Ok(None),
635    };
636    Ok(Some(repeated))
637}
638
639/// A sequence's elements laid out `count` times over.
640fn repeated_elements(items: &[Object], count: usize) -> Vec<Object> {
641    let mut repeated = Vec::with_capacity(items.len().saturating_mul(count));
642    for _ in 0..count {
643        repeated.extend(items.iter().cloned());
644    }
645    repeated
646}
647
648/// Whether a repetition of this size is one to attempt at all.
649fn room(len: usize, count: usize, element: usize) -> Result<()> {
650    let bytes = u64::try_from(len)
651        .ok()
652        .and_then(|len| len.checked_mul(u64::try_from(count).ok()?))
653        .and_then(|total| total.checked_mul(u64::try_from(element).ok()?));
654    match bytes {
655        Some(bytes) if bytes <= REPEAT_LIMIT => Ok(()),
656        _ => Err(Error::new(Kind::MemoryError, "")),
657    }
658}
659
660/// The four ordering comparisons, which not every pair of objects answers.
661fn order(op: Compare, left: &Object, right: &Object) -> Result<bool> {
662    if let (Some(a), Some(b)) = (number(left), number(right)) {
663        // A NaN is on neither side of anything, so all four are false for it.
664        return Ok(numeric_order(a, b).is_some_and(|ordering| op.decide(ordering)));
665    }
666    match (left, right) {
667        (Object::Str(a), Object::Str(b)) => Ok(op.decide(a.code_points().cmp(b.code_points()))),
668        (Object::Bytes(a), Object::Bytes(b)) => Ok(op.decide(a.cmp(b))),
669        (Object::Tuple(a), Object::Tuple(b)) => sequence_order(op, a, b),
670        (Object::List(a), Object::List(b)) => sequence_order(op, &a.borrow(), &b.borrow()),
671        (Object::Set(a), Object::Set(b)) => {
672            // A set is ordered by containment rather than by size, so two sets
673            // can be unequal with neither one less than the other.
674            let (a, b) = (a.borrow(), b.borrow());
675            let subset = a.len() <= b.len() && a.iter().all(|key| b.contains(key));
676            let superset = b.len() <= a.len() && b.iter().all(|key| a.contains(key));
677            Ok(match op {
678                Compare::Lt => subset && !superset,
679                Compare::Le => subset,
680                Compare::Gt => superset && !subset,
681                Compare::Ge => superset,
682                Compare::Eq | Compare::Ne => unreachable!("equality never reaches here"),
683            })
684        }
685        _ => Err(Error::type_error(format!(
686            "'{}' not supported between instances of '{}' and '{}'",
687            op.symbol(),
688            left.type_name(),
689            right.type_name()
690        ))),
691    }
692}
693
694/// Two sequences compared the way Python compares them, which is by finding the
695/// first place they differ and asking the operator about that pair alone.
696///
697/// It is not a lexicographic ordering built from a total order on the elements,
698/// because the elements need not have one. `(1, 'a') < (1, 2)` is a `TypeError`
699/// about a `str` and an `int`, and `(1, 'a') < (2, 'a')` is `True` without ever
700/// looking at the strings.
701fn sequence_order(op: Compare, left: &[Object], right: &[Object]) -> Result<bool> {
702    for (a, b) in left.iter().zip(right) {
703        if !a.same_value(b) {
704            return order(op, a, b);
705        }
706    }
707    Ok(op.decide(left.len().cmp(&right.len())))
708}
709
710/// How two numbers order, or `None` for a NaN, which orders against nothing.
711///
712/// Nothing here converts. An integer with a thousand digits compares against a
713/// float exactly, which is why `2 ** 2000 > 1e308` is an answer and
714/// `2 ** 2000 + 1.0` is an `OverflowError`.
715fn numeric_order(left: Num<'_>, right: Num<'_>) -> Option<Ordering> {
716    match (left, right) {
717        (Num::Int(a), Num::Int(b)) => Some(a.cmp(b)),
718        (Num::Float(a), Num::Float(b)) => a.partial_cmp(&b),
719        (Num::Int(a), Num::Float(b)) => int_cmp_float(a, b),
720        (Num::Float(a), Num::Int(b)) => int_cmp_float(b, a).map(Ordering::reverse),
721    }
722}
723
724/// How an integer orders against a float, exactly and without converting
725/// either one.
726#[expect(
727    clippy::cast_possible_truncation,
728    reason = "the cast is guarded by the range check above it, and the float is \
729              known to be integral there, so it is exact"
730)]
731fn int_cmp_float(int: &Int, float: f64) -> Option<Ordering> {
732    if float.is_nan() {
733        return None;
734    }
735    if float.is_infinite() {
736        return Some(if float > 0.0 {
737            Ordering::Less
738        } else {
739            Ordering::Greater
740        });
741    }
742    let whole = float.trunc();
743    let fraction = zero_cmp(float - whole);
744    if let Int::Small(value) = int
745        && (-9_223_372_036_854_775_808.0..9_223_372_036_854_775_808.0).contains(&whole)
746    {
747        return Some(value.cmp(&(whole as i64)).then(fraction));
748    }
749    let whole = BigInt::from_f64(whole).expect("a finite truncated float is an integer");
750    Some(int.to_big().cmp(&whole).then(fraction))
751}
752
753/// The fractional part read as an ordering, which is how a tie on the whole
754/// part is broken: a positive fraction makes the float the larger of the two.
755fn zero_cmp(fraction: f64) -> Ordering {
756    if fraction > 0.0 {
757        Ordering::Less
758    } else if fraction < 0.0 {
759        Ordering::Greater
760    } else {
761        Ordering::Equal
762    }
763}
764
765/// Whether the needle appears in the haystack, by code point.
766fn substring(haystack: &Str, needle: &Str) -> bool {
767    if let (Str::Utf8(haystack), Str::Utf8(needle)) = (haystack, needle) {
768        return haystack.contains(needle.as_ref());
769    }
770    // At least one of them holds a lone surrogate, which has no UTF-8 to search
771    // in, so the search happens over code points instead.
772    let haystack: Vec<u32> = haystack.code_points().collect();
773    let needle: Vec<u32> = needle.code_points().collect();
774    subslice(&haystack, &needle)
775}
776
777/// Whether the needle appears in the haystack, as a run.
778fn subslice<T: PartialEq>(haystack: &[T], needle: &[T]) -> bool {
779    // Every sequence contains the empty one, including the empty one, and
780    // `windows(0)` panics rather than saying so.
781    needle.is_empty()
782        || (needle.len() <= haystack.len()
783            && haystack.windows(needle.len()).any(|run| run == needle))
784}
785
786/// This value as a hashable key, or the exception a lookup raises when it
787/// cannot be one.
788///
789/// `role` is what the value was being used as, which 3.14 puts in front of the
790/// old `unhashable type` message: a `set element`, a `dict key`.
791///
792/// The two type names in that message need not be the same one. The first is
793/// what was handed over and the second is what inside it refused, and for a
794/// tuple holding a list those are `tuple` and `list`. The second is the one to
795/// go and fix, which is why the old message says that one.
796///
797/// # Errors
798///
799/// A list, a dict, a set, or a tuple containing one of those.
800pub fn key(value: &Object, role: &str) -> Result<Key> {
801    Key::new(value.clone()).map_err(|unhashable| {
802        Error::type_error(format!(
803            "cannot use '{}' as a {role} ({})",
804            value.type_name(),
805            unhashable.message()
806        ))
807    })
808}
809
810/// What every divisor of zero raises, whichever operator found it.
811fn divide_by_zero() -> Error {
812    Error::zero_division("division by zero")
813}
814
815/// The message a binary operator gives when neither operand knows what to do
816/// with the other.
817fn unsupported(symbol: &str, left: &Object, right: &Object) -> Error {
818    Error::type_error(format!(
819        "unsupported operand type(s) for {symbol}: '{}' and '{}'",
820        left.type_name(),
821        right.type_name()
822    ))
823}
824
825/// The message `+` gives, which the sequence types write themselves rather than
826/// leaving to the generic one, and which they only get to write when they are
827/// on the left.
828fn concat_error(left: &Object, right: &Object) -> Error {
829    let named = |kind| {
830        Error::type_error(format!(
831            "can only concatenate {kind} (not \"{}\") to {kind}",
832            right.type_name()
833        ))
834    };
835    match left {
836        Object::Str(_) => named("str"),
837        Object::List(_) => named("list"),
838        Object::Tuple(_) => named("tuple"),
839        Object::Bytes(_) => {
840            Error::type_error(format!("can't concat {} to bytes", right.type_name()))
841        }
842        _ => unsupported("+", left, right),
843    }
844}
845
846/// The message `*` gives, which is about the count when one side is a sequence
847/// and about the pair when neither is.
848fn repeat_error(left: &Object, right: &Object) -> Error {
849    let sequence = |value: &Object| {
850        matches!(
851            value,
852            Object::Str(_) | Object::Bytes(_) | Object::Tuple(_) | Object::List(_)
853        )
854    };
855    // The right operand gets asked second and so is the one that raises, which
856    // is why it is the left type that gets named when both are sequences.
857    let culprit = if sequence(right) {
858        Some(left)
859    } else if sequence(left) {
860        Some(right)
861    } else {
862        None
863    };
864    match culprit {
865        Some(culprit) => Error::type_error(format!(
866            "can't multiply sequence by non-int of type '{}'",
867            culprit.type_name()
868        )),
869        None => unsupported("*", left, right),
870    }
871}
872
873/// The message a unary operator gives for a type it does not apply to.
874fn bad_unary(symbol: &str, value: &Object) -> Error {
875    Error::type_error(format!(
876        "bad operand type for unary {symbol}: '{}'",
877        value.type_name()
878    ))
879}
880
881#[cfg(test)]
882mod tests {
883    use super::*;
884
885    fn i(value: i64) -> Object {
886        Object::int(value)
887    }
888
889    fn two_to(power: i64) -> Object {
890        Object::Int(
891            Int::Small(2)
892                .pow(&Int::Small(power))
893                .expect("a power this size fits"),
894        )
895    }
896
897    fn f(value: f64) -> Object {
898        Object::Float(value)
899    }
900
901    fn s(value: &str) -> Object {
902        Object::str(value)
903    }
904
905    fn y(value: &[u8]) -> Object {
906        Object::Bytes(value.into())
907    }
908
909    fn t(items: Vec<Object>) -> Object {
910        Object::tuple(items)
911    }
912
913    fn l(items: Vec<Object>) -> Object {
914        Object::list(items)
915    }
916
917    fn set(items: Vec<Object>) -> Object {
918        Object::set(
919            items
920                .into_iter()
921                .map(|item| Key::new(item).expect("a hashable member"))
922                .collect(),
923        )
924    }
925
926    fn dict(pairs: Vec<(Object, Object)>) -> Object {
927        Object::dict(
928            pairs
929                .into_iter()
930                .map(|(key, value)| (Key::new(key).expect("a hashable key"), value))
931                .collect(),
932        )
933    }
934
935    /// A string built code point by code point, which is the only way to get a
936    /// lone surrogate into one.
937    fn wide(points: &[u32]) -> Object {
938        let mut buf = StrBuf::new();
939        for point in points {
940            buf.push_code_point(*point);
941        }
942        Object::Str(Rc::new(buf.finish()))
943    }
944
945    /// The repr of what an operator answered, which is what CPython prints.
946    fn ok(result: Result<Object>) -> String {
947        result.expect("an answer").repr()
948    }
949
950    /// The last line of the traceback an operator raised.
951    fn bad(result: Result<Object>) -> String {
952        result.expect_err("an exception").to_string()
953    }
954
955    #[test]
956    fn numbers_add_across_their_types() {
957        assert_eq!(ok(add(&i(1), &i(2))), "3");
958        assert_eq!(ok(add(&Object::Bool(true), &Object::Bool(true))), "2");
959        assert_eq!(ok(add(&i(1), &f(0.5))), "1.5");
960        assert_eq!(ok(add(&f(0.5), &Object::Bool(true))), "1.5");
961    }
962
963    #[test]
964    fn sequences_join_only_with_their_own_kind() {
965        assert_eq!(ok(add(&s("ab"), &s("cd"))), "'abcd'");
966        assert_eq!(ok(add(&y(b"ab"), &y(b"cd"))), "b'abcd'");
967        assert_eq!(ok(add(&t(vec![i(1)]), &t(vec![i(2)]))), "(1, 2)");
968        assert_eq!(ok(add(&l(vec![i(1)]), &l(vec![i(2)]))), "[1, 2]");
969    }
970
971    /// `x + x` reads the same list twice, and taking one borrow at a time is
972    /// what keeps that an answer rather than a panic.
973    #[test]
974    fn a_list_added_to_itself_is_it_twice_over() {
975        let items = l(vec![i(1)]);
976        assert_eq!(ok(add(&items, &items)), "[1, 1]");
977    }
978
979    #[test]
980    fn a_bad_addition_says_which_operand_it_is_about() {
981        assert_eq!(
982            bad(add(&i(1), &s("a"))),
983            "TypeError: unsupported operand type(s) for +: 'int' and 'str'"
984        );
985        assert_eq!(
986            bad(add(&s("a"), &i(1))),
987            "TypeError: can only concatenate str (not \"int\") to str"
988        );
989        assert_eq!(
990            bad(add(&s("a"), &y(b"b"))),
991            "TypeError: can only concatenate str (not \"bytes\") to str"
992        );
993        assert_eq!(
994            bad(add(&l(vec![i(1)]), &t(vec![i(2)]))),
995            "TypeError: can only concatenate list (not \"tuple\") to list"
996        );
997        assert_eq!(
998            bad(add(&t(vec![i(1)]), &l(vec![i(2)]))),
999            "TypeError: can only concatenate tuple (not \"list\") to tuple"
1000        );
1001        assert_eq!(
1002            bad(add(&y(b"a"), &s("a"))),
1003            "TypeError: can't concat str to bytes"
1004        );
1005        assert_eq!(
1006            bad(add(&y(b"a"), &i(1))),
1007            "TypeError: can't concat int to bytes"
1008        );
1009        assert_eq!(
1010            bad(add(&i(1), &l(vec![]))),
1011            "TypeError: unsupported operand type(s) for +: 'int' and 'list'"
1012        );
1013        assert_eq!(
1014            bad(add(&set(vec![i(1)]), &set(vec![i(2)]))),
1015            "TypeError: unsupported operand type(s) for +: 'set' and 'set'"
1016        );
1017    }
1018
1019    #[test]
1020    fn an_integer_too_large_for_a_float_says_so_rather_than_rounding() {
1021        let huge = two_to(2000);
1022        for result in [
1023            add(&huge, &f(1.0)),
1024            mul(&huge, &f(1.0)),
1025            floor_div(&huge, &f(1.0)),
1026            div_mod(&huge, &f(1.0)),
1027            pow(&huge, &f(0.5)),
1028        ] {
1029            assert_eq!(
1030                bad(result),
1031                "OverflowError: int too large to convert to float"
1032            );
1033        }
1034    }
1035
1036    /// Arithmetic converts and comparison does not, so an integer no float can
1037    /// hold still knows where it sits against one.
1038    #[test]
1039    fn a_comparison_against_a_float_stays_exact_however_large_the_integer() {
1040        let huge = two_to(2000);
1041        assert_eq!(ok(compare(Compare::Lt, &huge, &f(1.0))), "False");
1042        assert_eq!(ok(compare(Compare::Eq, &huge, &f(1.0))), "False");
1043        assert_eq!(ok(compare(Compare::Gt, &huge, &f(1e308))), "True");
1044        assert_eq!(ok(compare(Compare::Lt, &i(1), &f(1.5))), "True");
1045        assert_eq!(ok(compare(Compare::Gt, &i(2), &f(1.5))), "True");
1046        assert_eq!(ok(compare(Compare::Lt, &i(-2), &f(-1.5))), "True");
1047        assert_eq!(ok(compare(Compare::Lt, &i(1), &f(f64::INFINITY))), "True");
1048        assert_eq!(
1049            ok(compare(Compare::Gt, &huge, &f(f64::NEG_INFINITY))),
1050            "True"
1051        );
1052    }
1053
1054    #[test]
1055    fn a_sequence_repeats_by_an_integer_from_either_side() {
1056        assert_eq!(ok(mul(&s("ab"), &i(3))), "'ababab'");
1057        assert_eq!(ok(mul(&i(3), &s("ab"))), "'ababab'");
1058        assert_eq!(ok(mul(&Object::Bool(true), &s("ab"))), "'ab'");
1059        assert_eq!(ok(mul(&y(b"ab"), &i(2))), "b'abab'");
1060        assert_eq!(ok(mul(&t(vec![i(1)]), &i(3))), "(1, 1, 1)");
1061        assert_eq!(ok(mul(&i(3), &l(vec![i(0)]))), "[0, 0, 0]");
1062        assert_eq!(ok(mul(&wide(&[0xD800]), &i(2))), r"'\ud800\ud800'");
1063    }
1064
1065    /// What makes `'-' * (width - len(s))` safe to write without checking that
1066    /// the width has not already been passed.
1067    #[test]
1068    fn a_count_below_one_gives_an_empty_sequence_rather_than_an_error() {
1069        assert_eq!(ok(mul(&s("a"), &i(-1))), "''");
1070        assert_eq!(ok(mul(&s("a"), &i(0))), "''");
1071        assert_eq!(ok(mul(&l(vec![i(1)]), &i(-1))), "[]");
1072    }
1073
1074    #[test]
1075    fn a_count_that_is_not_an_integer_names_itself() {
1076        assert_eq!(
1077            bad(mul(&s("a"), &f(1.5))),
1078            "TypeError: can't multiply sequence by non-int of type 'float'"
1079        );
1080        assert_eq!(
1081            bad(mul(&f(1.5), &s("a"))),
1082            "TypeError: can't multiply sequence by non-int of type 'float'"
1083        );
1084        assert_eq!(
1085            bad(mul(&Object::None, &s("a"))),
1086            "TypeError: can't multiply sequence by non-int of type 'NoneType'"
1087        );
1088        assert_eq!(
1089            bad(mul(&s("a"), &Object::None)),
1090            "TypeError: can't multiply sequence by non-int of type 'NoneType'"
1091        );
1092        assert_eq!(
1093            bad(mul(&set(vec![i(1)]), &i(2))),
1094            "TypeError: unsupported operand type(s) for *: 'set' and 'int'"
1095        );
1096        assert_eq!(
1097            bad(mul(&Object::None, &Object::None)),
1098            "TypeError: unsupported operand type(s) for *: 'NoneType' and 'NoneType'"
1099        );
1100    }
1101
1102    #[test]
1103    fn a_repetition_no_machine_could_hold_is_refused_before_it_is_attempted() {
1104        assert_eq!(
1105            bad(mul(&s("a"), &two_to(63))),
1106            "OverflowError: cannot fit 'int' into an index-sized integer"
1107        );
1108        assert_eq!(
1109            bad(mul(&s("a"), &i(1_000_000_000_000_000_000))),
1110            "MemoryError"
1111        );
1112        assert_eq!(
1113            bad(mul(&l(vec![i(1)]), &i(1_000_000_000_000_000_000))),
1114            "MemoryError"
1115        );
1116    }
1117
1118    #[test]
1119    fn dividing_gives_a_float_however_the_operands_are_spelled() {
1120        assert_eq!(ok(true_div(&i(1), &i(2))), "0.5");
1121        assert_eq!(ok(true_div(&i(4), &i(2))), "2.0");
1122        assert_eq!(ok(true_div(&f(1.0), &i(2))), "0.5");
1123    }
1124
1125    #[test]
1126    fn every_divisor_of_zero_raises_the_same_thing() {
1127        for result in [
1128            true_div(&i(1), &i(0)),
1129            floor_div(&i(1), &i(0)),
1130            modulo(&i(1), &i(0)),
1131            div_mod(&i(1), &i(0)),
1132            true_div(&f(1.0), &i(0)),
1133            floor_div(&f(1.0), &i(0)),
1134            modulo(&f(1.0), &i(0)),
1135            div_mod(&f(7.0), &i(0)),
1136            true_div(&f(1.0), &f(-0.0)),
1137        ] {
1138            assert_eq!(bad(result), "ZeroDivisionError: division by zero");
1139        }
1140    }
1141
1142    #[test]
1143    fn a_quotient_with_no_float_to_land_on_says_so() {
1144        assert_eq!(
1145            bad(true_div(&two_to(2000), &i(1))),
1146            "OverflowError: integer division result too large for a float"
1147        );
1148        assert_eq!(ok(true_div(&i(1), &two_to(2000))), "0.0");
1149    }
1150
1151    #[test]
1152    fn flooring_goes_down_and_the_remainder_takes_the_divisors_sign() {
1153        assert_eq!(ok(floor_div(&i(7), &i(-3))), "-3");
1154        assert_eq!(ok(modulo(&i(7), &i(-3))), "-2");
1155        assert_eq!(ok(modulo(&i(-7), &i(3))), "2");
1156        assert_eq!(ok(div_mod(&i(7), &i(-3))), "(-3, -2)");
1157        assert_eq!(ok(floor_div(&f(7.0), &f(-2.0))), "-4.0");
1158        assert_eq!(ok(modulo(&f(-5.5), &f(2.0))), "0.5");
1159        assert_eq!(ok(modulo(&f(5.5), &f(-2.0))), "-0.5");
1160        assert_eq!(ok(div_mod(&f(-7.0), &f(-2.0))), "(3.0, -1.0)");
1161    }
1162
1163    /// The quotient is computed by dividing and then corrected, and the
1164    /// correction is what makes this fourteen instead of thirteen.
1165    #[test]
1166    fn a_float_quotient_keeps_the_bits_the_division_would_have_lost() {
1167        assert_eq!(ok(floor_div(&f(7.0), &f(0.5))), "14.0");
1168        assert_eq!(ok(floor_div(&f(1e308), &f(1e-10))), "inf");
1169    }
1170
1171    #[test]
1172    fn a_zero_quotient_and_a_zero_remainder_each_keep_a_sign() {
1173        assert_eq!(ok(floor_div(&f(-0.0), &f(1.0))), "-0.0");
1174        assert_eq!(ok(floor_div(&f(0.0), &f(-1.0))), "-0.0");
1175        assert_eq!(ok(modulo(&f(4.0), &f(-2.0))), "-0.0");
1176    }
1177
1178    #[test]
1179    fn raising_to_a_power_leaves_the_integers_when_the_exponent_is_negative() {
1180        assert_eq!(ok(pow(&i(2), &i(10))), "1024");
1181        assert_eq!(ok(pow(&i(0), &i(0))), "1");
1182        assert_eq!(ok(pow(&i(2), &i(-2))), "0.25");
1183        assert_eq!(ok(pow(&i(-2), &i(-1))), "-0.5");
1184        assert_eq!(ok(pow(&Object::Bool(true), &i(-1))), "1.0");
1185        assert_eq!(ok(pow(&i(2), &f(0.5))), "1.4142135623730951");
1186        assert_eq!(ok(pow(&f(0.0), &i(0))), "1.0");
1187        assert_eq!(ok(pow(&i(1), &f(f64::INFINITY))), "1.0");
1188    }
1189
1190    #[test]
1191    fn zero_to_a_negative_power_is_its_own_exception() {
1192        for result in [
1193            pow(&i(0), &i(-1)),
1194            pow(&f(0.0), &f(-1.0)),
1195            pow(&f(-0.0), &i(-1)),
1196        ] {
1197            assert_eq!(bad(result), "ZeroDivisionError: zero to a negative power");
1198        }
1199    }
1200
1201    #[test]
1202    fn a_power_that_runs_off_the_top_of_a_double_reports_what_the_c_library_said() {
1203        assert_eq!(
1204            bad(pow(&f(2.0), &i(10000))),
1205            "OverflowError: (34, 'Result too large')"
1206        );
1207        assert_eq!(
1208            bad(pow(&f(1e300), &i(2))),
1209            "OverflowError: (34, 'Result too large')"
1210        );
1211        assert_eq!(ok(pow(&f(f64::INFINITY), &i(2))), "inf");
1212    }
1213
1214    #[test]
1215    fn a_negative_base_to_a_fractional_power_needs_complex_numbers() {
1216        assert_eq!(
1217            bad(pow(&i(-2), &f(0.5))),
1218            "NotImplementedError: a negative number raised to a fractional power is a \
1219             complex number, and complex numbers are not implemented yet"
1220        );
1221        assert_eq!(ok(pow(&f(-1.0), &f(2.0))), "1.0");
1222    }
1223
1224    #[test]
1225    fn a_bad_power_names_both_of_its_spellings() {
1226        assert_eq!(
1227            bad(pow(&i(1), &s("a"))),
1228            "TypeError: unsupported operand type(s) for ** or pow(): 'int' and 'str'"
1229        );
1230    }
1231
1232    #[test]
1233    fn shifting_needs_a_count_that_is_not_negative() {
1234        assert_eq!(
1235            ok(lshift(&i(1), &i(100))),
1236            "1267650600228229401496703205376"
1237        );
1238        assert_eq!(ok(rshift(&i(-1), &i(100))), "-1");
1239        assert_eq!(ok(rshift(&i(1), &i(1_000_000))), "0");
1240        assert_eq!(ok(lshift(&Object::Bool(true), &i(1))), "2");
1241        assert_eq!(
1242            bad(lshift(&i(1), &i(-1))),
1243            "ValueError: negative shift count"
1244        );
1245        assert_eq!(
1246            bad(rshift(&i(1), &i(-1))),
1247            "ValueError: negative shift count"
1248        );
1249        assert_eq!(
1250            bad(lshift(&i(1), &i(1_000_000_000_000_000_000))),
1251            "MemoryError"
1252        );
1253        assert_eq!(
1254            bad(lshift(&i(1), &f(1.0))),
1255            "TypeError: unsupported operand type(s) for <<: 'int' and 'float'"
1256        );
1257    }
1258
1259    /// The one place a bitwise operator does not widen to `int`, which is why
1260    /// `True & True` is `True` and `True + True` is `2`.
1261    #[test]
1262    fn two_bools_give_a_bool_and_anything_else_gives_an_int() {
1263        assert_eq!(
1264            ok(bit_and(&Object::Bool(true), &Object::Bool(true))),
1265            "True"
1266        );
1267        assert_eq!(
1268            ok(bit_or(&Object::Bool(true), &Object::Bool(false))),
1269            "True"
1270        );
1271        assert_eq!(
1272            ok(bit_xor(&Object::Bool(true), &Object::Bool(true))),
1273            "False"
1274        );
1275        assert_eq!(ok(bit_and(&Object::Bool(true), &i(1))), "1");
1276        assert_eq!(ok(bit_and(&i(6), &i(3))), "2");
1277        assert_eq!(ok(rshift(&Object::Bool(true), &Object::Bool(true))), "0");
1278    }
1279
1280    #[test]
1281    fn the_bitwise_operators_are_the_set_operators_too() {
1282        let a = set(vec![i(1), i(2)]);
1283        assert_eq!(ok(sub(&a, &set(vec![i(2)]))), "{1}");
1284        assert_eq!(ok(bit_or(&a, &set(vec![i(3)]))), "{1, 2, 3}");
1285        assert_eq!(ok(bit_and(&a, &set(vec![i(2)]))), "{2}");
1286        assert_eq!(ok(bit_xor(&a, &set(vec![i(2)]))), "{1}");
1287        // A set holds one of every value rather than one of every object, so a
1288        // float that equals a member it already has is a member it already has.
1289        assert_eq!(ok(sub(&set(vec![i(1)]), &set(vec![f(1.0)]))), "set()");
1290        assert_eq!(ok(bit_or(&set(vec![i(1)]), &set(vec![f(1.0)]))), "{1}");
1291        assert_eq!(
1292            bad(bit_or(&a, &l(vec![i(1)]))),
1293            "TypeError: unsupported operand type(s) for |: 'set' and 'list'"
1294        );
1295        assert_eq!(
1296            bad(sub(&a, &l(vec![i(1)]))),
1297            "TypeError: unsupported operand type(s) for -: 'set' and 'list'"
1298        );
1299    }
1300
1301    #[test]
1302    fn the_unary_operators_widen_a_bool_to_the_integer_it_is() {
1303        assert_eq!(ok(neg(&Object::Bool(true))), "-1");
1304        assert_eq!(ok(pos(&Object::Bool(true))), "1");
1305        assert_eq!(ok(invert(&Object::Bool(true))), "-2");
1306        assert_eq!(ok(neg(&f(1.5))), "-1.5");
1307        assert_eq!(ok(invert(&i(1))), "-2");
1308        assert_eq!(
1309            bad(invert(&f(1.5))),
1310            "TypeError: bad operand type for unary ~: 'float'"
1311        );
1312        assert_eq!(
1313            bad(pos(&s("a"))),
1314            "TypeError: bad operand type for unary +: 'str'"
1315        );
1316        assert_eq!(
1317            bad(neg(&Object::None)),
1318            "TypeError: bad operand type for unary -: 'NoneType'"
1319        );
1320    }
1321
1322    #[test]
1323    fn abs_drops_the_sign_and_the_bool_with_it() {
1324        assert_eq!(ok(abs(&i(-3))), "3");
1325        assert_eq!(ok(abs(&i(3))), "3");
1326        assert_eq!(ok(abs(&Object::Bool(true))), "1");
1327        assert_eq!(ok(abs(&f(-1.5))), "1.5");
1328        // A negative zero has a sign and no magnitude, so this is the one case
1329        // where the answer is not the number back.
1330        assert_eq!(ok(abs(&f(-0.0))), "0.0");
1331        // The message names the function rather than an operator, which is the
1332        // one way it differs from the three above it.
1333        assert_eq!(
1334            bad(abs(&s("a"))),
1335            "TypeError: bad operand type for abs(): 'str'"
1336        );
1337    }
1338
1339    #[test]
1340    fn not_answers_for_every_object() {
1341        assert_eq!(not(&s("a")).repr(), "False");
1342        assert_eq!(not(&l(vec![])).repr(), "True");
1343        assert_eq!(not(&Object::None).repr(), "True");
1344        assert_eq!(not(&Object::Ellipsis).repr(), "False");
1345    }
1346
1347    #[test]
1348    fn numbers_compare_across_their_types() {
1349        assert_eq!(ok(compare(Compare::Lt, &Object::Bool(true), &i(2))), "True");
1350        assert_eq!(ok(compare(Compare::Le, &i(1), &f(1.0))), "True");
1351        assert_eq!(ok(compare(Compare::Eq, &f(0.0), &f(-0.0))), "True");
1352        assert_eq!(ok(compare(Compare::Gt, &f(1.5), &i(1))), "True");
1353        assert_eq!(ok(compare(Compare::Ne, &i(1), &f(1.0))), "False");
1354    }
1355
1356    #[test]
1357    fn a_nan_is_on_neither_side_of_anything() {
1358        let nan = f(f64::NAN);
1359        for op in [
1360            Compare::Lt,
1361            Compare::Le,
1362            Compare::Gt,
1363            Compare::Ge,
1364            Compare::Eq,
1365        ] {
1366            assert_eq!(ok(compare(op, &nan, &i(1))), "False");
1367            assert_eq!(ok(compare(op, &nan, &nan)), "False");
1368        }
1369        assert_eq!(ok(compare(Compare::Ne, &nan, &nan)), "True");
1370    }
1371
1372    #[test]
1373    fn a_sequence_compares_at_the_first_place_it_differs() {
1374        assert_eq!(
1375            ok(compare(
1376                Compare::Lt,
1377                &l(vec![i(1), i(2)]),
1378                &l(vec![i(1), i(2), i(3)])
1379            )),
1380            "True"
1381        );
1382        assert_eq!(ok(compare(Compare::Lt, &t(vec![]), &t(vec![i(1)]))), "True");
1383        assert_eq!(ok(compare(Compare::Lt, &s("abc"), &s("abd"))), "True");
1384        assert_eq!(ok(compare(Compare::Lt, &s("Z"), &s("a"))), "True");
1385        assert_eq!(ok(compare(Compare::Lt, &y(&[0]), &y(&[1]))), "True");
1386        assert_eq!(
1387            ok(compare(
1388                Compare::Lt,
1389                &t(vec![i(1), s("a")]),
1390                &t(vec![i(2), s("a")])
1391            )),
1392            "True"
1393        );
1394        // The elements that differ are the ones the operator is asked about,
1395        // and they need not have an order between them.
1396        assert_eq!(
1397            bad(compare(
1398                Compare::Lt,
1399                &t(vec![i(1), s("a")]),
1400                &t(vec![i(1), i(2)])
1401            )),
1402            "TypeError: '<' not supported between instances of 'str' and 'int'"
1403        );
1404    }
1405
1406    /// A container asks `x is y or x == y` about its elements, so a NaN that is
1407    /// the same object on both sides counts as equal and the comparison never
1408    /// reaches it.
1409    #[test]
1410    fn a_sequence_checks_identity_first_and_a_nan_shows_it() {
1411        let nan = f(f64::NAN);
1412        assert_eq!(
1413            ok(compare(
1414                Compare::Eq,
1415                &t(vec![nan.clone()]),
1416                &t(vec![nan.clone()])
1417            )),
1418            "True"
1419        );
1420        assert_eq!(
1421            ok(compare(
1422                Compare::Lt,
1423                &t(vec![nan.clone()]),
1424                &t(vec![nan.clone()])
1425            )),
1426            "False"
1427        );
1428        assert_eq!(
1429            ok(compare(
1430                Compare::Le,
1431                &t(vec![nan.clone()]),
1432                &t(vec![nan.clone()])
1433            )),
1434            "True"
1435        );
1436        assert_eq!(
1437            ok(compare(
1438                Compare::Lt,
1439                &t(vec![i(1), nan]),
1440                &t(vec![i(1), i(2)])
1441            )),
1442            "False"
1443        );
1444    }
1445
1446    #[test]
1447    fn a_set_is_ordered_by_containment_rather_than_by_size() {
1448        assert_eq!(
1449            ok(compare(
1450                Compare::Lt,
1451                &set(vec![i(1)]),
1452                &set(vec![i(1), i(2)])
1453            )),
1454            "True"
1455        );
1456        assert_eq!(
1457            ok(compare(Compare::Lt, &set(vec![i(1)]), &set(vec![i(2)]))),
1458            "False"
1459        );
1460        assert_eq!(
1461            ok(compare(Compare::Gt, &set(vec![i(1)]), &set(vec![i(2)]))),
1462            "False"
1463        );
1464        assert_eq!(
1465            ok(compare(Compare::Le, &set(vec![i(1)]), &set(vec![i(1)]))),
1466            "True"
1467        );
1468        assert_eq!(
1469            ok(compare(
1470                Compare::Gt,
1471                &set(vec![i(1), i(2)]),
1472                &set(vec![i(1)])
1473            )),
1474            "True"
1475        );
1476    }
1477
1478    #[test]
1479    fn a_pair_with_no_order_says_so_and_still_answers_equality() {
1480        assert_eq!(
1481            bad(compare(Compare::Lt, &i(1), &s("a"))),
1482            "TypeError: '<' not supported between instances of 'int' and 'str'"
1483        );
1484        assert_eq!(
1485            bad(compare(Compare::Le, &i(1), &s("a"))),
1486            "TypeError: '<=' not supported between instances of 'int' and 'str'"
1487        );
1488        assert_eq!(
1489            bad(compare(Compare::Lt, &Object::None, &Object::None)),
1490            "TypeError: '<' not supported between instances of 'NoneType' and 'NoneType'"
1491        );
1492        assert_eq!(
1493            bad(compare(Compare::Lt, &l(vec![i(1)]), &t(vec![i(1)]))),
1494            "TypeError: '<' not supported between instances of 'list' and 'tuple'"
1495        );
1496        assert_eq!(
1497            bad(compare(Compare::Lt, &s("a"), &y(b"a"))),
1498            "TypeError: '<' not supported between instances of 'str' and 'bytes'"
1499        );
1500        assert_eq!(
1501            bad(compare(
1502                Compare::Lt,
1503                &dict(vec![(i(1), i(2))]),
1504                &dict(vec![(i(1), i(3))])
1505            )),
1506            "TypeError: '<' not supported between instances of 'dict' and 'dict'"
1507        );
1508        assert_eq!(
1509            ok(compare(Compare::Eq, &Object::None, &Object::None)),
1510            "True"
1511        );
1512        assert_eq!(ok(compare(Compare::Ne, &i(1), &s("a"))), "True");
1513    }
1514
1515    #[test]
1516    fn a_string_contains_strings_and_nothing_else() {
1517        assert_eq!(ok(contains(&s("xaby"), &s("ab"))), "True");
1518        assert_eq!(ok(contains(&s("abc"), &s(""))), "True");
1519        assert_eq!(ok(contains(&s("abc"), &s("d"))), "False");
1520        assert_eq!(
1521            bad(contains(&s("abc"), &i(1))),
1522            "TypeError: 'in <string>' requires string as left operand, not int"
1523        );
1524    }
1525
1526    /// A lone surrogate has no UTF-8 to search in, so the search goes over code
1527    /// points instead and finds the same answers.
1528    #[test]
1529    fn a_substring_search_works_on_a_string_that_has_no_utf8() {
1530        let text = wide(&[u32::from('a'), 0xD800, u32::from('b')]);
1531        assert_eq!(ok(contains(&text, &wide(&[0xD800]))), "True");
1532        assert_eq!(ok(contains(&text, &s("ab"))), "False");
1533        assert_eq!(ok(contains(&text, &s("b"))), "True");
1534    }
1535
1536    #[test]
1537    fn a_bytes_contains_runs_of_bytes_and_single_byte_values() {
1538        assert_eq!(ok(contains(&y(b"abc"), &y(b"ab"))), "True");
1539        assert_eq!(ok(contains(&y(b"abc"), &y(b"x"))), "False");
1540        assert_eq!(ok(contains(&y(b"abc"), &i(i64::from(b'a')))), "True");
1541        assert_eq!(ok(contains(&y(b"abc"), &i(1))), "False");
1542        assert_eq!(
1543            bad(contains(&y(b"abc"), &i(256))),
1544            "ValueError: byte must be in range(0, 256)"
1545        );
1546        assert_eq!(
1547            bad(contains(&y(b"abc"), &i(-1))),
1548            "ValueError: byte must be in range(0, 256)"
1549        );
1550        assert_eq!(
1551            bad(contains(&y(b"abc"), &s("a"))),
1552            "TypeError: a bytes-like object is required, not 'str'"
1553        );
1554    }
1555
1556    #[test]
1557    fn a_lookup_by_an_unhashable_key_names_what_it_was_being_used_as() {
1558        assert_eq!(
1559            bad(contains(&set(vec![i(1)]), &l(vec![]))),
1560            "TypeError: cannot use 'list' as a set element (unhashable type: 'list')"
1561        );
1562        assert_eq!(
1563            bad(contains(&dict(vec![(i(1), i(2))]), &l(vec![]))),
1564            "TypeError: cannot use 'list' as a dict key (unhashable type: 'list')"
1565        );
1566        // Two different type names, because the tuple is what was handed over
1567        // and the list inside it is what refused.
1568        assert_eq!(
1569            bad(contains(
1570                &dict(vec![(i(1), i(2))]),
1571                &t(vec![l(vec![]), i(1)])
1572            )),
1573            "TypeError: cannot use 'tuple' as a dict key (unhashable type: 'list')"
1574        );
1575        assert_eq!(
1576            bad(contains(&set(vec![i(1)]), &t(vec![l(vec![]), i(1)]))),
1577            "TypeError: cannot use 'tuple' as a set element (unhashable type: 'list')"
1578        );
1579    }
1580
1581    #[test]
1582    fn a_container_is_searched_by_value_and_everything_else_is_not_a_container() {
1583        assert_eq!(ok(contains(&t(vec![i(1), i(2)]), &i(1))), "True");
1584        assert_eq!(
1585            ok(contains(&l(vec![l(vec![i(1)])]), &l(vec![i(1)]))),
1586            "True"
1587        );
1588        assert_eq!(ok(contains(&dict(vec![(i(1), i(2))]), &f(1.0))), "True");
1589        assert_eq!(ok(contains(&dict(vec![]), &s("a"))), "False");
1590        assert_eq!(ok(contains(&set(vec![s("a")]), &s("a"))), "True");
1591        assert_eq!(
1592            bad(contains(&Object::None, &i(1))),
1593            "TypeError: argument of type 'NoneType' is not a container or iterable"
1594        );
1595        assert_eq!(
1596            bad(contains(&i(2), &i(1))),
1597            "TypeError: argument of type 'int' is not a container or iterable"
1598        );
1599    }
1600}
1601
1602/// `container[index]`.
1603///
1604/// # Errors
1605///
1606/// A container that has no subscript, a subscript of the wrong type, an index
1607/// past the end, or a key nothing is filed under.
1608pub fn get_item(container: &Object, index: &Object) -> Result<Object> {
1609    match container {
1610        Object::List(items) => {
1611            match subscript(index, items.borrow().len(), Seq::List, Write::No)? {
1612                Subscript::At(at) => Ok(items.borrow()[at].clone()),
1613                Subscript::Range(range) => {
1614                    let items = items.borrow();
1615                    Ok(Object::list(
1616                        range.offsets().map(|at| items[at].clone()).collect(),
1617                    ))
1618                }
1619            }
1620        }
1621        Object::Tuple(items) => match subscript(index, items.len(), Seq::Tuple, Write::No)? {
1622            Subscript::At(at) => Ok(items[at].clone()),
1623            Subscript::Range(range) => Ok(Object::tuple(
1624                range.offsets().map(|at| items[at].clone()).collect(),
1625            )),
1626        },
1627        Object::Str(text) => match subscript(index, text.len(), Seq::Str, Write::No)? {
1628            // A one code point string, which is what `str` has instead of a
1629            // character type.
1630            Subscript::At(at) => {
1631                let mut out = StrBuf::new();
1632                out.push_code_point(text.code_point_at(at).expect("the index was checked"));
1633                Ok(Object::Str(Rc::new(out.finish())))
1634            }
1635            Subscript::Range(range) => {
1636                // Collected once rather than walked per offset, because UTF-8
1637                // has no way to reach the nth code point without counting from
1638                // the front and doing that inside the loop would be quadratic.
1639                let points: Vec<u32> = text.code_points().collect();
1640                let mut out = StrBuf::new();
1641                for at in range.offsets() {
1642                    out.push_code_point(points[at]);
1643                }
1644                Ok(Object::Str(Rc::new(out.finish())))
1645            }
1646        },
1647        Object::Bytes(bytes) => match subscript(index, bytes.len(), Seq::Bytes, Write::No)? {
1648            // One byte of a `bytes` is an `int`, not a one byte `bytes`, which
1649            // is the difference between `bytes` and `str` that surprises people.
1650            Subscript::At(at) => Ok(Object::int(i64::from(bytes[at]))),
1651            Subscript::Range(range) => {
1652                let taken: Vec<u8> = range.offsets().map(|at| bytes[at]).collect();
1653                Ok(Object::Bytes(taken.into()))
1654            }
1655        },
1656        Object::Dict(entries) => {
1657            let key = key(index, "dict key")?;
1658            entries
1659                .borrow()
1660                .get(&key)
1661                .cloned()
1662                .ok_or_else(|| missing_key(index))
1663        }
1664        other => Err(not_subscriptable(other)),
1665    }
1666}
1667
1668/// `container[index] = value`.
1669///
1670/// # Errors
1671///
1672/// A container that cannot be written through, an index past the end, or a
1673/// slice assignment whose right hand side is the wrong length.
1674pub fn set_item(container: &Object, index: &Object, value: &Object) -> Result<()> {
1675    match container {
1676        Object::List(items) => {
1677            let len = items.borrow().len();
1678            match subscript(index, len, Seq::List, Write::Yes)? {
1679                Subscript::At(at) => {
1680                    items.borrow_mut()[at] = value.clone();
1681                    Ok(())
1682                }
1683                Subscript::Range(range) => {
1684                    // Read the right hand side out before touching the list, so
1685                    // that `x[:] = x` sees the list it started with.
1686                    let replacement = elements(value).ok_or_else(|| {
1687                        Error::type_error("must assign iterable to extended slice")
1688                    })?;
1689                    let mut items = items.borrow_mut();
1690                    if range.is_contiguous() {
1691                        let start = range.start.cast_unsigned();
1692                        items.splice(start..start + range.len, replacement);
1693                        return Ok(());
1694                    }
1695                    if replacement.len() != range.len {
1696                        return Err(Error::value_error(format!(
1697                            "attempt to assign sequence of size {} to extended slice of size {}",
1698                            replacement.len(),
1699                            range.len
1700                        )));
1701                    }
1702                    for (at, value) in range.offsets().zip(replacement) {
1703                        items[at] = value;
1704                    }
1705                    Ok(())
1706                }
1707            }
1708        }
1709        Object::Dict(entries) => {
1710            entries
1711                .borrow_mut()
1712                .insert(key(index, "dict key")?, value.clone());
1713            Ok(())
1714        }
1715        // Everything else, subscriptable or not, says the same thing here:
1716        // having no subscript at all and having a read-only one are the same
1717        // answer to "can I write to this".
1718        other => Err(Error::type_error(format!(
1719            "'{}' object does not support item assignment",
1720            other.type_name()
1721        ))),
1722    }
1723}
1724
1725/// `del container[index]`.
1726///
1727/// # Errors
1728///
1729/// A container that cannot be written through, an index past the end, or a key
1730/// nothing is filed under.
1731pub fn del_item(container: &Object, index: &Object) -> Result<()> {
1732    match container {
1733        Object::List(items) => {
1734            let len = items.borrow().len();
1735            match subscript(index, len, Seq::List, Write::Yes)? {
1736                Subscript::At(at) => {
1737                    items.borrow_mut().remove(at);
1738                    Ok(())
1739                }
1740                Subscript::Range(range) => {
1741                    // Back to front, so that removing one does not move the
1742                    // offsets of the ones not yet removed.
1743                    let mut doomed: Vec<usize> = range.offsets().collect();
1744                    doomed.sort_unstable();
1745                    let mut items = items.borrow_mut();
1746                    for at in doomed.into_iter().rev() {
1747                        items.remove(at);
1748                    }
1749                    Ok(())
1750                }
1751            }
1752        }
1753        Object::Dict(entries) => entries
1754            .borrow_mut()
1755            .remove(&key(index, "dict key")?)
1756            .map(|_| ())
1757            .ok_or_else(|| missing_key(index)),
1758        // Two wordings, and which one a type gets is not arbitrary in CPython
1759        // even though it reads that way. A container without deletion says
1760        // "doesn't"; something that was never a container says "does not".
1761        Object::Tuple(_) | Object::Str(_) | Object::Bytes(_) | Object::Set(_) => {
1762            Err(Error::type_error(format!(
1763                "'{}' object doesn't support item deletion",
1764                container.type_name()
1765            )))
1766        }
1767        other => Err(Error::type_error(format!(
1768            "'{}' object does not support item deletion",
1769            other.type_name()
1770        ))),
1771    }
1772}
1773
1774/// How many elements a builtin container holds, or `None` for a value that has
1775/// no length.
1776///
1777/// `None` is not an error here. A `range` has a length too and is defined
1778/// above this crate, so the caller checks that itself before deciding nothing
1779/// has an answer.
1780#[must_use]
1781pub fn len(value: &Object) -> Option<usize> {
1782    Some(match value {
1783        Object::Str(text) => text.len(),
1784        Object::Bytes(bytes) => bytes.len(),
1785        Object::Tuple(items) => items.len(),
1786        Object::List(items) => items.borrow().len(),
1787        Object::Dict(entries) => entries.borrow().len(),
1788        Object::Set(members) => members.borrow().len(),
1789        _ => return None,
1790    })
1791}
1792
1793/// The values inside something that can be walked without the iteration
1794/// protocol, or `None` when it cannot be walked without one.
1795///
1796/// Every builtin container can be walked directly, which covers everything a
1797/// program can build today. When the iteration protocol arrives this becomes
1798/// the fast path in front of it rather than the whole of it.
1799#[must_use]
1800pub fn elements(value: &Object) -> Option<Vec<Object>> {
1801    match value {
1802        // Read out whole first, because the caller is usually about to write
1803        // into the thing it just read.
1804        Object::List(items) => Some(items.borrow().clone()),
1805        Object::Tuple(items) => Some(items.to_vec()),
1806        Object::Str(text) => Some(
1807            text.code_points()
1808                .map(|point| {
1809                    let mut out = StrBuf::new();
1810                    out.push_code_point(point);
1811                    Object::Str(Rc::new(out.finish()))
1812                })
1813                .collect(),
1814        ),
1815        // A byte of a `bytes` is an `int`, so walking one gives integers.
1816        Object::Bytes(bytes) => Some(bytes.iter().map(|&b| Object::int(i64::from(b))).collect()),
1817        // A dict walks its keys, which is what `list(d)` gives.
1818        Object::Dict(entries) => Some(
1819            entries
1820                .borrow()
1821                .iter()
1822                .map(|(key, _)| key.object().clone())
1823                .collect(),
1824        ),
1825        Object::Set(members) => Some(
1826            members
1827                .borrow()
1828                .iter()
1829                .map(|key| key.object().clone())
1830                .collect(),
1831        ),
1832        _ => None,
1833    }
1834}
1835
1836/// What a subscript turned out to mean for a particular sequence.
1837enum Subscript {
1838    /// One element, at an offset already checked against the length.
1839    At(usize),
1840    /// A run of them, already resolved against the length.
1841    Range(Indices),
1842}
1843
1844/// The four builtin sequences, which word a bad subscript three different ways.
1845#[derive(Clone, Copy)]
1846enum Seq {
1847    List,
1848    Tuple,
1849    Str,
1850    Bytes,
1851}
1852
1853impl Seq {
1854    /// The `TypeError` for a subscript that is neither an integer nor a slice.
1855    ///
1856    /// Three phrasings for four types, because CPython's messages were written
1857    /// one at a time rather than generated: a `str` leaves out "or slices" and
1858    /// quotes the type name, and a `bytes` calls itself "byte".
1859    fn not_an_index(self, index: &Object) -> Error {
1860        let name = index.type_name();
1861        Error::type_error(match self {
1862            Seq::List => format!("list indices must be integers or slices, not {name}"),
1863            Seq::Tuple => format!("tuple indices must be integers or slices, not {name}"),
1864            Seq::Bytes => format!("byte indices must be integers or slices, not {name}"),
1865            Seq::Str => format!("string indices must be integers, not '{name}'"),
1866        })
1867    }
1868
1869    /// The `IndexError` for an integer past the end.
1870    ///
1871    /// A list says "assignment" when it is being written through, and only a
1872    /// list can be, so the other three never see the second wording.
1873    fn out_of_range(self, write: Write) -> Error {
1874        Error::new(
1875            Kind::IndexError,
1876            match (self, write) {
1877                (Seq::List, Write::No) => "list index out of range",
1878                (Seq::List, Write::Yes) => "list assignment index out of range",
1879                (Seq::Tuple, _) => "tuple index out of range",
1880                (Seq::Str, _) => "string index out of range",
1881                (Seq::Bytes, _) => "index out of range",
1882            },
1883        )
1884    }
1885}
1886
1887/// Whether a subscript is being read or written through, which changes one
1888/// message and nothing else.
1889#[derive(Clone, Copy, PartialEq, Eq)]
1890enum Write {
1891    No,
1892    Yes,
1893}
1894
1895/// One subscript resolved against a sequence of `len` elements.
1896fn subscript(index: &Object, len: usize, seq: Seq, write: Write) -> Result<Subscript> {
1897    match index {
1898        Object::Slice(slice) => Ok(Subscript::Range(slice.indices(len)?)),
1899        Object::Bool(_) | Object::Int(_) => {
1900            let Some(Num::Int(at)) = number(index) else {
1901                unreachable!("an int and a bool are both numbers")
1902            };
1903            Ok(Subscript::At(offset(at, len, seq, write)?))
1904        }
1905        other => Err(seq.not_an_index(other)),
1906    }
1907}
1908
1909/// An integer index turned into an offset, with a negative one counted from the
1910/// end.
1911///
1912/// A number too large for the machine says so rather than being clamped, which
1913/// is the one place an index and a slice bound part company: `x[2**100]` raises
1914/// where `x[2**100:]` is an empty list. The two messages are different too, and
1915/// the difference is worth keeping: one says the sequence is not that long, the
1916/// other says the number was never an index to begin with.
1917fn offset(index: &Int, len: usize, seq: Seq, write: Write) -> Result<usize> {
1918    let too_big = || {
1919        Error::new(
1920            Kind::IndexError,
1921            "cannot fit 'int' into an index-sized integer",
1922        )
1923    };
1924    let at = index.to_i64().ok_or_else(too_big)?;
1925    let at = isize::try_from(at).map_err(|_| too_big())?;
1926    let at = if at < 0 {
1927        at.checked_add(len.cast_signed()).ok_or_else(too_big)?
1928    } else {
1929        at
1930    };
1931    if at < 0 || at.cast_unsigned() >= len {
1932        return Err(seq.out_of_range(write));
1933    }
1934    Ok(at.cast_unsigned())
1935}
1936
1937/// `KeyError`, which prints the key itself rather than a sentence about it.
1938///
1939/// Built out of the key rather than out of a message, so that a handler
1940/// catching it gets the key back. A `KeyError` is the one exception whose
1941/// message is already a `repr`, and rebuilding one from its message would put a
1942/// second pair of quotes around a string key.
1943fn missing_key(key: &Object) -> Error {
1944    Error::raised(Kind::KeyError, vec![key.clone()])
1945}
1946
1947/// The `TypeError` for a value that has no subscript at all.
1948fn not_subscriptable(value: &Object) -> Error {
1949    Error::type_error(format!(
1950        "'{}' object is not subscriptable",
1951        value.type_name()
1952    ))
1953}