use crate::{
args::{ArgValues, FromArgs},
bytecode::VM,
exception_private::{ExcType, ExcTypeExt, RunResult},
heap::HeapData,
types::{List, iter::collect_owned_iterable},
value::Value,
};
#[derive(FromArgs)]
#[from_args(name = "reversed", style = unpack)]
struct ReversedArgs {
#[from_args(pos_only)]
sequence: Value,
}
pub fn builtin_reversed(vm: &mut VM<'_>, args: ArgValues) -> RunResult<Value> {
let ReversedArgs { sequence } = ReversedArgs::from_args(args, vm)?;
if !is_reversible(&sequence, vm) {
let err = ExcType::type_error_not_reversible(&sequence.py_type_name(vm));
sequence.drop_with(vm);
return Err(err);
}
let mut items: Vec<_> = collect_owned_iterable(sequence, vm)?;
items.reverse();
let heap_id = vm.heap.allocate(HeapData::List(List::new(items)));
Ok(Value::Ref(heap_id))
}
fn is_reversible(value: &Value, vm: &VM<'_>) -> bool {
match value {
Value::InternString(_) | Value::InternBytes(_) => true,
Value::Ref(id) => matches!(
vm.heap.get(*id),
HeapData::List(_)
| HeapData::Tuple(_)
| HeapData::NamedTuple(_)
| HeapData::Deque(_)
| HeapData::Str(_)
| HeapData::Bytes(_)
| HeapData::Range(_)
| HeapData::Dict(_)
| HeapData::DictKeysView(_)
| HeapData::DictItemsView(_)
| HeapData::DictValuesView(_)
),
_ => false,
}
}